I'm having some problems with this login script, I've already had someone else look it over for me and we cannot seem to figure out what the issue is.
What's happening is when a user tries to login, if the the username is correct it will check if the password is correct and if the password is correct it updates the last access date and redirects like it is supposed to. However if the username is correct and the password is incorrect. It should empty out the password, and let the user know the password they entered is incorrect.
What actually happens when the password is incorrect, is it is skipping to the outermost else statement, and emptying out the username and password and saying there is an issue...whether or not the username entered is correct (regardless of whether or not the password is right).
I have no idea what is happening here, and hopefully someone can help me shed some light on it.
Thank you!
$selectUser = pg_prepare($dbConnection, "selectuser_query", 'SELECT * FROM users WHERE user_id = $1 AND password = $2');
<?php
$error = "";
$username_error = "";
$password_error = "";
if($_SERVER["REQUEST_METHOD"] == "GET")
{
$login = "";
$password = "";
}
else if($_SERVER["REQUEST_METHOD"] == "POST")
{
$login = trim($_POST["login"]);
$password = trim($_POST["password"]);
if(!isset($login) || $login == "")
{
$username_error = "You must enter your user name to login!";
}
if (!isset($password) || $password == "")
{
$password_error = "You must enter your password to login!";
}
if(($error == "") && ($password_error == "") && ($username_error == ""))
{
$selectUser = pg_execute($dbConnection, "selectuser_query", array("$login", "$password"));
if($login == pg_fetch_result($selectUser, "user_id"))
{
if($password == pg_fetch_result($selectUser, "password"))
{
$date = date("n-j-Y");
$updateDateAccess = pg_execute($dbConnection, "updatedate_query", array("'$date'", "$login"));
header('Location: ./welcome.php');
}
else
{
$password = "";
$error = "The password is incorrect. Please try again.";
}
}
else
{
$login = "";
$password = "";
$error = "The username/password is incorrect. Please try again.";
}
}
}
?>
Your problem is your query:
SELECT * FROM users WHERE user_id = $1 AND password = $2
It checks both the username and password, which results in no records being returned if the password is incorrect. Thus, the next if condition isn't satisfied:
$selectUser = pg_execute($dbConnection, "selectuser_query", array("$login", "$password")); // no records
if($login == pg_fetch_result($selectUser, "user_id")) // not satisfied, because there are no records
{
// ...
}
else // this runs
{
$login = "";
$password = "";
$error = "The username/password is incorrect. Please try again.";
}
What you want to do is run a query that retrieves the (salted and hashed) password for a given username, then check the password in your application logic.
Also, as others have pointed out in the comments, this is not a good way to store passwords or respond to incorrect info. It looks like the passwords are in plain text, but they should be hashed and salted. Also, you should not tell the user which part of the information was incorrect; otherwise, you let an attacker determine valid usernames and then focus on brute-forcing those.
Related
ive looked all over the internet to try to solve this problem and i cant find figure it out for the life of me. Really starting to give up.
So basically whenever i login with the correct email and correct password it says incorrect email or password. This only happens whenever i hash the password in the db
Email: test#gmail.com
Password: testtest
Hash: $2y$10$hk3d/GyYvImcxYR.vdC2/.JDIeQeXyKdTSPifueAkQNrYVBcMn1Yi
Anyways if someone could help me that would be amazing here is my login.php code.
<?php
require "../private/php/autoload.php";
$error = "";
if($_SERVER['REQUEST_METHOD'] == "POST" && isset($_SESSION['token']) && isset($_POST['token']) && $_SESSION['token'] == $_POST['token']){
$email = $_POST['email'];
if(!preg_match("/^[\w\-]+#[\w\-]+.[\w\-]+$/", $email)){
$error = "Please enter a valid email.";
}
$password = $_POST['password'];
if ($error == ""){
$arr['email'] = $email;
$arr['password'] = $password;
$query = "SELECT * FROM users WHERE email = :email && password = :password LIMIT 1";
$stm = $conn->prepare($query);
$check = $stm->execute($arr);
if($check){
$data = $stm->fetchAll(PDO::FETCH_OBJ);
if(is_array($data) && count($data) > 0){
$data = $data[0];
if (password_verify($_POST['password'], $data->password)){
$_SESSION['username'] = $data->username;
$_SESSION['user_id'] = $data->user_id;
header("Location: index.php");
die;
}
}
}
}
$error = "Wrong email or password!";
}
$_SESSION['token'] = get_random_string(30);
?>```
Your MySQL table contains the password hashed, but you're querying it passing through the un-hashed password which is why it's not matching/working presently.
Also, worth noting that this could be bad from a security point of view as the plaintext password is being transmitted and could easily end up in your MySQL logs (Slow Log, Error if there was any issue etc.).
Swap the query out to just look up on the email address alone (assuming it's unique), and then verify the password hashes match in your PHP logic against the MySQL result.
I'm trying to make a login system (already have registration system complete) with password_hash() and password_verify() but it isn't working for me. I've been trying to find an answer this whole morning and yet can't seem to make it work, I've watched codecourse tutorials, read blog posts and nothing. The tutorial I've been following the most is this one.
<!-- login -->
<?php
if($_SERVER['REQUEST_METHOD'] == "POST") {
$errors = array();
error_reporting(E_ALL);
ini_set('display_errors', 1);
//Basic validation
if(empty($_POST['username'])){
$errors[] = "Please enter your username";
}else{
$username = $mysqli->real_escape_string($_POST['username']);
}
if(empty($_POST['password'])){
$errors[] = "Please enter your password";
}else{
$password = trim($_POST['password']);
}
if (empty($errors)) {
$sql = "SELECT * FROM users WHERE username = '$username'";
$result = $mysqli->query($sql);
if ($result->num_rows === 1) {
$row = $result->fetch_array(MYSQLI_ASSOC);
if(password_verify($password, $row['password'])) {
echo 'test';
$_SESSION['user']['user_id'] = $row['user'];
header("Location: google.com");
exit();
}else{
$errors[] = "The username or password do not match";
}
}else{
$errors[] = "The username or password do not match";
}
}
}
?>
<!-- register -->
<?php
if($_SERVER['REQUEST_METHOD'] == "POST") {
$username = mysqli_real_escape_string($conn, $_POST['username']);
$password = $_POST['password'];
$hashed_password = password_hash($password, PASSWORD_DEFAULT);
$confirm_password = mysqli_real_escape_string($conn, $password);
$ip = $_SERVER['REMOTE_ADDR'];
if(empty($username) || empty($password) || empty($confirm_password)) {
$error = "Fill in the missing fields";
} else {
$sql = "INSERT INTO users VALUES('', '$username', '$hashed_password', '$ip', 'User')";
if($conn->query($sql) === TRUE) {
$error = "Your account has been created.";
} else {
$error = "Your account has not been created, please try again later.";
}
}
}
?>
The end result product is supposed to login in successfully and redirect, I'm using PHP 5.6 and running on localhost XAMPP.
You'll never get a match because you're using
$password =mysqli_real_escape_string($conn, $_POST['password']);
to store the password and then not using it on verification. Instead you use
$password = trim($_POST['password']);
Make sure you don't escape passwords or use any other cleansing mechanism on them before hashing. Doing so changes the password and causes unnecessary additional coding. The password_hash() function can generate some very lengthy text (the current default is 60 characters), so make sure the field in your database is large enough to accommodate the hash. Setting the field larger now will allow for the length needed. The PHP team is adding more algorithms to the method which means the hash can and will grow.
I created a script to log users into a website, however I can never get authenticated, even with the right password. Everything else works properly. This script is activated by pressing a login button after typing a username and password in textboxes. Below is the script:
<?php
session_start();
include('connection.php');
//STEP 2 Declare Variables
$Name = $_POST['username'];
$Pass = md5($_POST['password']); // Encrypt password with md5() function.
$Query = mysql_query("SELECT * FROM Users WHERE username='$Name' AND password='$Pass'");
$NumRows = mysql_num_rows($Query);
$_SESSION['username'] = $Name;
$_SESSION['password'] = $Pass;
//STEP 3 Check to See If User Entered All Of The Information
if(empty($_SESSION['username']) || empty($_SESSION['password']))
{
die("Go back and login before you visit this page!");
}
if($Name && $Pass == "")
{
die("Please enter in a name and password!");
}
if($Name == "")
{
die("Please enter your name!" . "</br>");
}
if($Pass == "")
{
die("Please enter a password!");
echo "</br>";
}
//STEP 4 Check Username And Password With The MySQL Database
if($NumRows)
{
// If The User Makes It Here Then That Means He Logged In Successfully
echo "";
$_SESSION['username']=$Database_Name;
}
else
{
die("Incorrect Username or Password!");
}
?>
After I login I get "Incorrect Username or Password!", even though the username and password entered are correct. The passwords are being entered as md5() hashes in the database. This script worked years ago when I first created it. Posted below is a screenshot of the DB. Any help would be greatly appreciated
Here is a picture of a user in my DB named Bob who is using an MD5 hash of the word "Password" as his Password.
Here is a picture of the echoed results when he tries to login.
This code:
if($NumRows != 0)
{
while($Row = mysql_fetch_assoc($Query))
{
$Database_Name = $Row['username'];
$Database_Pass = $Row['password'];
}
}
else
{
die("Incorrect Username or Password!");
}
if($Name == $Database_Name && $Pass == $Database_Pass)
{
// If The User Makes It Here Then That Means He Logged In Successfully
echo "";
$_SESSION['username']=$Database_Name;
}
Can be simplified by using only mysql_num_rows:
if($NumRows) {
// If The User Makes It Here Then That Means He Logged In Successfully
echo "";
$_SESSION['username']=$Database_Name;
} else {
die("Incorrect Username or Password!");
}
Explanation:
Since, you are using mysql_num_rows, it will return 1 row if your query matches, thus the user is already authenticated, else it will return 0. Using mysql_fetch_assoc then comparing the results is redundant.
if($NumRows) will return 1 if one row matches, and 1 is true.
Update:
It's most probably due to length of field in your database being too short to successfully insert the whole md5() hash. Thus, the latter part did not insert successfully.
IMPORTANT:
You should not be using MySQL as it is already deprecated, use MySQLi instead. MySQL functions are not available in PHP 7.
Also, you need to prevent MySQL Injection by using mysql_real_escape_string.
md5() isn't a very secure way of storing passwords, instead use crypt().
if(isset($_POST['login'])) {
$username = mysql_real_escape_string($_POST['username']);
$password = mysql_real_escape_string($_POST['password']);
if(empty($username) || empty($password)) {
$error = 1;
$error_message = 'Please fill in all the required fields.';
} else {
get_login_name($username, $password);
//The commented line works...
//$query = mysql_query("SELECT /* user_logged true, page login */username, password FROM members WHERE username = '".$username."' AND password = '".sha1($password)."' LIMIT 1");
}
if(mysql_num_rows(get_login_name($username, $password)) == 0) {
echo get_login_name($username, $password);
$error = 1;
$error_message = 'Incorrect username or password.';
} elseif ($error == 0) {
//Other stuff....
}
}
Function:
function get_login_name($password, $username) {
global $myDB;
global $config;
$query = "SELECT /* page == login, functions.php */username, password FROM members WHERE username = '".$username."' AND password = '".sha1($password)."' LIMIT 1";
$result = $myDB->Execute($query) or die(GetDbError($myDB->ErrorMsg()));
return $result;
}
How properly check if username or password incorrect ? (part if(mysql_num_rows(g.....)
In my opinion something wrong i have done ir function get_login_name with return and checking. By the way, using adodb.
EDIT:
After all i decided a bit test it, so, let's leave function as it now and let's check username and password part:
if (!is_null(get_login_name($password, $username))) {
echo get_login_name($password, $username);
$error = 1;
$error_message = 'Incorrect username or password.';
}
If username or password incorrect ir gives me:
username,password which mean result doesn't found at all (no user, if user correct gives same)
Ok, let's enter valid user and pass, and it gaves:
username,password zero,0a706ce75f3bc195c8ed7be5a21d3766abb0d384
What's wrong ?
Essentially, if get_login_name has a return, that means the query returned a match for username and password which means the combination is correct, otherwise, no result means there's no match so you could say either username or password is incorrect (because they don't exist or one of them is wrong). If $Result has a value using get_login_name would likely to be just:
if (!is_null(get_login_name($password, $username)))
// correct
else
// incorrect
Play around with it and see the results.
Ech, after testing managed it to work :)
That seems this part fails :/
if (!is_null(get_login_name($password, $username)))
So, hole code:
if (!$myDB->Affected_Rows()) {
//if(mysql_num_rows($query) == 0) {
$error = 1;
$error_message = 'Incorrect username or password.';
}
What i have ? Just changed it to:
if (!$myDB->Affected_Rows()) {
Thank you all guys who tryed help.
I would like to accomplish the following:
If a username or password field is null, notify the user. If user name already exists, do not insert into the database and notify user to create a different name. if the username is unique and password is not null, return the username to the user.
As of now it always returns "Please enter a different user name." I believe the issue has to do with the database query but I am not sure. If anyone can have a look and see if I am making an error, I greatly appreciate it, thanks.
if ($userName or $userPassword = null)
{
echo "Please enter a user name and password or return to the homepage.";
}
elseif (mysql_num_rows(mysql_query("SELECT count(userName) FROM logininfo WHERE userName = '$userName'")) ==1)
{
echo "Please enter a different user name.";
}
elseif ($userName and $userPassword != null)
{
echo "Your login name is: $userName";
}
if ($userName or $userPassword = null)
This checks if the $userName is true (equivalent to $userName == true), and you're assigning null to $userPassword. You want something like $userName == '' || $userPassword == ''.
"SELECT count(userName) FROM logininfo WHERE userName = '$userName'"
Risk of SQL injection. Use mysql_real_escape_string before plugging values into queries!
Also, mysql_num_rows will always return 1 row, hence this expression is always true. You need to look at the value of this one row.
elseif ($userName and $userPassword != null)
If this check was what you'd intend it to be, it'd be redundant with the first check.
Use something like this:
function validateUser($username, $password) {
if ($username == '' || $password == '') {
return 'Please enter a user name and password or return to the homepage.';
}
$query = sprintf("SELECT COUNT(*) as `count` FROM `logininfo` WHERE `userName` = '%s'",
mysql_real_escape_string($username));
$result = mysql_query($query);
if (!$result) {
trigger_error(mysql_error());
return false;
}
$result = mysql_fetch_assoc($result);
if ($result['count'] > 0) {
return 'Please enter a different user name.';
}
return "Username: $username";
}
$result = validateUser($username, $password);
if (!$result) {
// something went wrong, deal with it
} else {
echo htmlentities($result);
}
Note that this is still far from ideal code, but I hope you get the idea.
if ($userName or $userPassword = null)
should be
if (($userName == null) or ($userPassword == null))
However, I suspect you don't actually want to check if these are null. Assuming you're filling these variables from input fields, an empty text field is NOT null; it's an empty string. You can do !empty($userName) to check for an empty text field.
If you want to check two variable in single conditional, you have to write out each check separately - ($userName and $userPassword != null) won't work the way you expect it to, it should be ($userName != NULL and $userPassword != null).
Also, when you're checking if a variable is equal to something, you have to use the == operator. Otherwise, you're assigning the variable to that value, which is pretty much never what you want to do.
You might need the below. Very basic, though.
isset($_POST['username']) or die('username not given'); //#1
isset($_POST['password']) or die('password not given'); //#2
$escapedUsername = mysql_real_escape_string($_POST);
$result = mysql_fetch_array(mysql_query("SELECT count(userName) FROM logininfo WHERE userName = '$escapedUsername'"))
if ($result){
echo "Hello, $escapedUsername"; //#3
}else{
echo "Invalid Password"; //#4
}
But may I suggest something different. Will require you to change some portions of your app though.
have this file as some login.php
Use this for login/password reset/register/etc..
have a GET to differentiate between these requests
Use AJAX.
In that case replace the following something like the below:
#1 : die('{"RESULT":"ERROR", "DESC" : "USERNAME NOT GIVEN"}');
#2 : die('{"RESULT":"ERROR", "DESC" : "PASSWORD NOT GIVEN"}');
#3 : die('{"RESULT":"ERROR", "DESC" : "INVALID USERNAME/PWD"}');
#4 : die('{"RESULT":"SUCCESS", "DESC" : "$escapedUsername"}'); // can also use json_encode($result) here.
These are just my suggestions. I have assumed mysql doesnt give you any problem. :-)