Tom10 Posted March 14, 2015 Share Posted March 14, 2015 I'm trying to make a login script using prepared statements $stmt = $con->prepare("SELECT username, password FROM users WHERE username=? AND password=?"); $stmt->bind_param("ss", $username, $password); $stmt->execute(); $res = $stmt->get_result(); $res->num_rows; if($stmt) { echo "yes"; } else { echo "no"; } Since i cannot actually get it to login i'm just getting it to echo yes or no to check if the statement is working, if i type the correct username but the wrong password it echo's yes Quote Link to comment Share on other sites More sharing options...
Tom10 Posted March 14, 2015 Author Share Posted March 14, 2015 Never mind i found what i did wrong i changed if($stmt) to if($res->num_rows > 0) and also i forgot to add the hash algorithm in the login script Quote Link to comment Share on other sites More sharing options...
Tom10 Posted March 14, 2015 Author Share Posted March 14, 2015 $password = hash('gost-crypto', $password); $stmt = $con->prepare("SELECT username, password, status FROM users WHERE username=? AND password=? AND status=?"); $stmt->bind_param("ssi", $username, $password, $status); $stmt->execute(); $res = $stmt->get_result(); $status = $res->fetch_assoc(); $res->num_rows; if($res->num_rows > 0) { if($status = "0") { echo "banned."; } else { echo "notbanned."; } I can't get this to work i'm trying to check the status of an account Quote Link to comment Share on other sites More sharing options...
maxxd Posted March 14, 2015 Share Posted March 14, 2015 You're using the status as a parameter for your query, so it's only going to return records that match the username, password, and the supplied status. Keep 'status' in your select field list, but don't use it in the conditional. That way you'll pull the record that matches the username, password, and any status. Then you can check the value of that status and be on your way. Quote Link to comment Share on other sites More sharing options...
maxxd Posted March 14, 2015 Share Posted March 14, 2015 Basically, change this: $stmt = $con->prepare("SELECT username, password, status FROM users WHERE username=? AND password=? AND status=?"); $stmt->bind_param("ssi", $username, $password, $status); to this: $stmt = $con->prepare("SELECT username, password, status FROM users WHERE username=? AND password=?"); $stmt->bind_param("ss", $username, $password); The rest of your script should work as you expect. Quote Link to comment Share on other sites More sharing options...
Tom10 Posted March 14, 2015 Author Share Posted March 14, 2015 This part is not working correctly if($status == 0) { echo "banned."; } else { echo "notbanned."; } the status column in the table is set to 0 and it says the account is not banned. Quote Link to comment Share on other sites More sharing options...
iarp Posted March 15, 2015 Share Posted March 15, 2015 (edited) That's because $status is an array containing the rows that were returned by the query. Do a print_r($status) and you'll see what it contains. Looking at your code i would imagine it'll contain an array of arrays, but it's possible it could just contain the single rows data. echo $status[0]['status']; # or echo $status['status']; BTW you cannot trust num_rows to always return the number of rows it returned, it returns the number of affected rows by the query you issued, if you wanted to be safe you'd need to issue a COUNT(*) statement to get a proper count. Or you could do a COUNT($status) or COUNT($res). The only reason I cannot nail down what to expect from your query is you have some strange things going on, I'm not sure what the purpose of doing this is $res = $stmt->get_result(); $status = $res->fetch_assoc(); $res->num_rows; You should be able to just do (below) and be done with it, then you could issue COUNT($rows) and know how many were returned. $rows = $stmt->fetchAll(); if (count($rows) > 0) { foreach ($rows as $row) { .... Do whatever you want in here foreach row returned } # or $status = $row[0]; if($status['status'] == 0) { echo 'banned'; } else { echo 'not banned'; } } Edited March 15, 2015 by iarp Quote Link to comment Share on other sites More sharing options...
JustThatGuy Posted March 15, 2015 Share Posted March 15, 2015 (edited) lol, you're not even doing it right. $stmt = $con->prepare("SELECT username, password FROM users WHERE username = ? AND password = ?"); $stmt->bind_param("ss", $username, $password); $stmt->execute(); $stmt->store_result(); if($stmt->num_rows) { echo "yes"; } else { echo "no"; } You should use store_result instead of get_result and you're using num_rows wrong. If you want to check if the account is banned or not. Find out if the account actually exists first. Then do something like. $stmt = $con->prepare("SELECT username, password, status FROM users WHERE username = ? AND password = ?"); $stmt->bind_param("ss", $username, $password); $stmt->execute(); $stmt->store_result(); if($stmt->num_rows) { $stmt->bind_result($username, $password, $status); while($stmt->fetch()) if($status == 0) { echo "Banned"; } else { echo "regular user"; } } else { echo "no"; } num_rows already checks for the user inputted variables. It's really redundant to use > 0 with num_rows because let's say the user logs in with guest as the username and password as the password. num_rows already checks if those two return a row. Checking to see if the row is greater than 0 is exactly what num_rows already has done. Your problem is that you aren't using PHP correctly and there for, won't allow you to login with what ever you're attempting. If you want to use the built-in password hash, you have to check if the user exists first. Then if the user does exist, take their hashed password from the database and compare it with the password they have entered in using the password_verify function. If the passwords do not match when they actually do match then you are doing something wrong. Edited March 15, 2015 by JustThatGuy Quote Link to comment Share on other sites More sharing options...
Tom10 Posted March 15, 2015 Author Share Posted March 15, 2015 It doesn't work Quote Link to comment Share on other sites More sharing options...
mac_gyver Posted March 15, 2015 Share Posted March 15, 2015 It doesn't work sorry, but we cannot help you based on that statement. several different things were mentioned or suggested and your exact code determines what the computer tried to do. without knowing what your code is and what incorrect result, error, or symptom you got from that code, we cannot help. several of the things you have shown in your code (this and previous threads) are invalid and would be throwing php errors. do you have php's error_reporting set to E_ALL and display_errors set ON in the php.ini on your development system so that php would help you by displaying all the errors it detects? you will save a ton of time. putting these setting into your code won't do anything for php syntax errors in your main file, as the code never runs to modify the error_reporting/display_errors settings. also, by having your development system set up with these settings, you don't need to remember to turn the settings on for development and turn them off if the code is ever moved to a live server because the setting will be tied to the server and not your code files. next, your code itself does not have any error checking logic in it to detect when statements fail. most of the database statements can fail due to an error of some kind and you should be checking at each step if they failed or not so that you don't throw follow-on errors in later statements when an earlier statement failed. for example, if the ->prepare() statement failed (due to a syntax error in the sql statement), there's no point in trying to bind input parameters or to execute the query. you can either add a conditional statement around each database statement that can fail or you can turn on exceptions for the mysqli statements (see the mysqli_report() statement) and either catch the exceptions yourself (which you would want to do for a real application) or let the uncaught exceptions be caught by php and stop execution and display the information about the error. some critique of your code in this thread (some of these have already been found and fixed by you or pointed out by others) - post #1 - $res->num_rows; just having this on a line by itself doesn't accomplish anything. the ->num_rows property returns a value. you must either assign that value to a variable or use the value in a conditional statement (or pass it as a value to another function.) if($stmt) { this tests if $stmt is a true value. $stmt is the result of the ->prepare() statement. it will be a true value as long as the prepare() didn't fail. post #3 - AND status = ? as a condition in the WHERE clause in the sql query statement. this would be okay if you are trying to find records that have a specific status value, i.e. all the user's that have status = 0, but for what you have stated you are trying to do, authenticate/log in a user, you would not have this as a condition in the WHERE clause, but instead retrieve this value and display a message to the person trying to log in. $status = $res->fetch_assoc(); this fetches the row that the query might have matched, as an associative array. this should be inside the conditional block of code that has tested if the query did match at least one row, since $status will be a false value, not an array, if there was no row to fetch. you still have a $res->num_rows; statement on a line by itself, which doesn't do anything. if($status = "0") { this actually assigns the "0" string to $status, then tests the result of that. one = is an assignment operator. two == are needed for a comparison operator. and as has already been mentioned, $status = $res->fetch_assoc(); will result in $status being an associative array. $status['status'] would actually hold the value from the status column in the database table. it would perhaps be easier to keep the code straight if you use a variable named $row - $row = $res->fetch_assoc();, then use $row['status'] to reference the status column value. finally, php has password hash functions - password_hash()/password_verify(), that produces a random salt for each hashed password, making it little harder for anyone getting a hold of your data to come up with the the original passwords, since they must brute force break each one separately. if you switch to using these functions, you would use password_hash() during registration. to authenticate the visitor, you would retrieve the hashed value from the database table and use password_verify() to test if the entered password corresponds to the hashed password. as always, there are basic examples for all the php functions in the php.net documentation. Quote Link to comment Share on other sites More sharing options...
Tom10 Posted March 15, 2015 Author Share Posted March 15, 2015 <?php session_start(); error_reporting(E_ALL | E_NOTICE); ini_set('display_errors', 1); require 'connect.php'; if(isset($_POST['submit'])) { $disallowed = "<h1>Your username or password has disallowed characters!</h1>".PHP_EOL."Please make sure that you have no spaces or characters such as:<h3><li>".PHP_EOL." \"\!\^\$\*\@\#\~ </li></h3>".PHP_EOL."<li><h3>Also make sure that there are no spaces in your username or password.</h3></li>".PHP_EOL."Thanks, ".PHP_EOL." System Administrator."; $username = $_POST['username']; $password = $_POST['password']; if(preg_match("#[^\w\b]#", $username)) { echo $disallowed; exit(); } if(preg_match("#[^\w\b]#", $password)) { echo $disallowed; exit(); } $password = hash('gost-crypto', $password); $stmt = $con->prepare("SELECT username, password FROM users WHERE username = ? AND password = ?"); $stmt->bind_param("ss", $username, $password); $stmt->execute(); $stmt->store_result(); if($stmt->num_rows) { $stmt->bind_result($username, $password, $status); while($stmt->fetch()) if($status == 0) { echo "Banned"; } else { echo "regular user"; } } else { echo "no"; } } ?> <html lang="en"><meta charset="utf-8"><head></head><title>Login to your account!</title> <body> <center> <span style="font-size: 32px; font-weight: bold; font-family: Arial; padding; 10px;"> Please Login </span> </center> <link rel="stylesheet" href="css/login.css" /> <div class="login"> <center> <form action="" method="POST"> <br><br>Username: <br><input type="text" name="username" placeholder="Username" required /> <br><br>Paswsord: <br><input type="password" name="password" placeholder="Password" required /> <br><br><input type="submit" name="submit" value="Login to your account!" /> </center> </div> </form> </body> </html> Quote Link to comment Share on other sites More sharing options...
JustThatGuy Posted March 15, 2015 Share Posted March 15, 2015 (edited) Try this <?php session_start(); error_reporting(E_ALL | E_NOTICE); ini_set('display_errors', 1); require 'connect.php'; // Use $_SERVER['REQUEST_METHOD'] // Here is an article on why you shouldn't use $_POST['submit'] // http://stackoverflow.com/questions/10943060/isset-postsubmit-vs-serverrequest-method-post#comment14373814_10943179 // Read those comments if($_SERVER['REQUEST_METHOD'] == "POST") { $disallowed = "<h1>Your username has disallowed characters!</h1>".PHP_EOL."Please make sure that you have no spaces or characters such as:<h3><li>".PHP_EOL." \"\!\^\$\*\@\#\~ </li></h3>".PHP_EOL."<li><h3>Also make sure that there are no spaces in your username.</h3></li>".PHP_EOL."Thanks, ".PHP_EOL." System Administrator."; $username = $_POST['username']; if(preg_match("#[^\w\b]#", $username)) { echo $disallowed; exit(); } // The above is only needed for the username. By limiting the amount of characters the user can use can result in weak passwords. By allowing them to use such characters !^$*@#, they strengthening their password. You don't need to whitelist these characters because SQL injections does not come from user input, it comes from bad codes. $stmt = $con->prepare("SELECT username, password, status FROM users WHERE username = ?"); // Just only need the username so we can verify the password $stmt->bind_param("s", $username); // Bind the variables so there won't be any SQL injections $stmt->execute(); // Executes the query $stmt->store_result(); // Stores the results for later checking // Checks to see if the query has returned a row if($stmt->num_rows) { // The username exists $post_password = $_POST['password']; // We finally check for the password because we only needed the username in the beginning $stmt->bind_result($username, $password, $status); while($stmt->fetch()) if(password_verify($post_password, $password)) { echo "Success!"; // The account exists with the right password } else { echo "Wrong password"; // The wrong password has been typed in } } else { echo "No Account"; // This should be a custom error saying that the account does not exist or something like they have typed int he wrong password and username } } else { ?> <html lang="en"><meta charset="utf-8"><head></head><title>Login to your account!</title> <body> <center> <span style="font-size: 32px; font-weight: bold; font-family: Arial; padding; 10px;"> Please Login </span> </center> <link rel="stylesheet" href="css/login.css" /> <div class="login"> <center> <form action="" method="POST"> <br><br>Username: <br><input type="text" name="username" placeholder="Username" required /> <br><br>Paswsord: <br><input type="password" name="password" placeholder="Password" required /> <br><br><input type="submit" name="submit" value="Login to your account!" /> </center> </div> </form> </body> </html><?php } If you use this, you'll need to redo your whole password algorithm. You'll have to start using password_hash and password_verify. Edited March 15, 2015 by JustThatGuy Quote Link to comment Share on other sites More sharing options...
Tom10 Posted March 15, 2015 Author Share Posted March 15, 2015 (edited) I got my code to work, i'm having problems with the status though <?php session_start(); error_reporting(E_ALL | E_NOTICE); ini_set('display_errors', 1); require 'connect.php'; if(isset($_POST['submit'])) { $disallowed = "<h1>Your username or password has disallowed characters!</h1>".PHP_EOL."Please make sure that you have no spaces or characters such as:<h3><li>".PHP_EOL." \"\!\^\$\*\@\#\~ </li></h3>".PHP_EOL."<li><h3>Also make sure that there are no spaces in your username or password.</h3></li>".PHP_EOL."Thanks, ".PHP_EOL." System Administrator."; $username = $_POST['username']; $password = $_POST['password']; if(preg_match("#[^\w\b]#", $username)) { echo $disallowed; exit(); } if(preg_match("#[^\w\b]#", $password)) { echo $disallowed; exit(); } $password = hash('gost-crypto', $password); $stmt = $con->prepare("SELECT username, password FROM users WHERE username = ? AND password = ?"); $stmt->bind_param("ss", $username, $password); $stmt->execute(); $stmt->store_result(); $status = $stmt->fetch(); if($stmt->num_rows > 0) { if($status < 1) { header("Location: banned.php"); } else { header("Location: user.php"); } } else { echo "Your username or password is incorrect. Please try again."; } } $con->close(); ?> <html lang="en"><meta charset="utf-8"><head></head><title>Login to your account!</title> <body> <center> <span style="font-size: 32px; font-weight: bold; font-family: Arial; padding; 10px;"> Please Login </span> </center> <link rel="stylesheet" href="css/login.css" /> <div class="login"> <center> <form action="" method="POST"> <br><br>Username: <br><input type="text" name="username" placeholder="Username" required /> <br><br>Paswsord: <br><input type="password" name="password" placeholder="Password" required /> <br><br><input type="submit" name="submit" value="Login to your account!" /> </center> </div> </form> </body> </html> Edited March 15, 2015 by Tom10 Quote Link to comment Share on other sites More sharing options...
Tom10 Posted March 15, 2015 Author Share Posted March 15, 2015 But your code makes a lot of sense and i will make changes Quote Link to comment Share on other sites More sharing options...
Tom10 Posted March 15, 2015 Author Share Posted March 15, 2015 Also i've never understood while loops Quote Link to comment Share on other sites More sharing options...
Tom10 Posted March 15, 2015 Author Share Posted March 15, 2015 <?php session_start(); error_reporting(E_ALL | E_NOTICE); ini_set('display_errors', 1); require 'connect.php'; // Use $_SERVER['REQUEST_METHOD'] // Here is an article on why you shouldn't use $_POST['submit'] // http://stackoverflow.com/questions/10943060/isset-postsubmit-vs-serverrequest-method-post#comment14373814_10943179 // Read those comments if($_SERVER['REQUEST_METHOD'] == "POST") { $disallowed = "<h1>Your username has disallowed characters!</h1>".PHP_EOL."Please make sure that you have no spaces or characters such as:<h3><li>".PHP_EOL." \"\!\^\$\*\@\#\~ </li></h3>".PHP_EOL."<li><h3>Also make sure that there are no spaces in your username.</h3></li>".PHP_EOL."Thanks, ".PHP_EOL." System Administrator."; $username = $_POST['username']; if(preg_match("#[^\w\b]#", $username)) { echo $disallowed; exit(); } // The above is only needed for the username. By limiting the amount of characters the user can use can result in weak passwords. By allowing them to use such characters !^$*@#, they strengthening their password. You don't need to whitelist these characters because SQL injections does not come from user input, it comes from bad codes. $stmt = $con->prepare("SELECT username, password, status FROM users WHERE username = ?"); // Just only need the username so we can verify the password $stmt->bind_param("s", $username); // Bind the variables so there won't be any SQL injections $stmt->execute(); // Executes the query $stmt->store_result(); // Stores the results for later checking // Checks to see if the query has returned a row if($stmt->num_rows) { // The username exists $post_password = $_POST['password']; // We finally check for the password because we only needed the username in the beginning $hash = password_hash($post_password, PASSWORD_DEFAULT); $stmt->bind_result($username, $password, $status); while($stmt->fetch()) if(password_verify($post_password, $password)) { echo "Success!"; // The account exists with the right password } else { echo "Wrong password"; // The wrong password has been typed in } } else { echo "No Account"; // This should be a custom error saying that the account does not exist or something like they have typed int he wrong password and username } } ?> <html lang="en"><meta charset="utf-8"><head></head><title>Login to your account!</title> <body> <center> <span style="font-size: 32px; font-weight: bold; font-family: Arial; padding; 10px;"> Please Login </span> </center> <link rel="stylesheet" href="css/login.css" /> <div class="login"> <center> <form action="" method="POST"> <br><br>Username: <br><input type="text" name="username" placeholder="Username" required /> <br><br>Paswsord: <br><input type="password" name="password" placeholder="Password" required /> <br><br><input type="submit" name="submit" value="Login to your account!" /> </center> </div> </form> </body> </html> It says wrong password Quote Link to comment Share on other sites More sharing options...
JustThatGuy Posted March 15, 2015 Share Posted March 15, 2015 (edited) <?php session_start(); error_reporting(E_ALL | E_NOTICE); ini_set('display_errors', 1); require 'connect.php'; // Use $_SERVER['REQUEST_METHOD'] // Here is an article on why you shouldn't use $_POST['submit'] // http://stackoverflow.com/questions/10943060/isset-postsubmit-vs-serverrequest-method-post#comment14373814_10943179 // Read those comments if($_SERVER['REQUEST_METHOD'] == "POST") { $disallowed = "<h1>Your username has disallowed characters!</h1>".PHP_EOL."Please make sure that you have no spaces or characters such as:<h3><li>".PHP_EOL." \"\!\^\$\*\@\#\~ </li></h3>".PHP_EOL."<li><h3>Also make sure that there are no spaces in your username.</h3></li>".PHP_EOL."Thanks, ".PHP_EOL." System Administrator."; $username = $_POST['username']; if(preg_match("#[^\w\b]#", $username)) { echo $disallowed; exit(); } // The above is only needed for the username. By limiting the amount of characters the user can use can result in weak passwords. By allowing them to use such characters !^$*@#, they strengthening their password. You don't need to whitelist these characters because SQL injections does not come from user input, it comes from bad codes. $stmt = $con->prepare("SELECT username, password, status FROM users WHERE username = ?"); // Just only need the username so we can verify the password $stmt->bind_param("s", $username); // Bind the variables so there won't be any SQL injections $stmt->execute(); // Executes the query $stmt->store_result(); // Stores the results for later checking // Checks to see if the query has returned a row if($stmt->num_rows) { // The username exists $post_password = $_POST['password']; // We finally check for the password because we only needed the username in the beginning $hash = password_hash($post_password, PASSWORD_DEFAULT); $stmt->bind_result($username, $password, $status); while($stmt->fetch()) if(password_verify($post_password, $password)) { echo "Success!"; // The account exists with the right password } else { echo "Wrong password"; // The wrong password has been typed in } } else { echo "No Account"; // This should be a custom error saying that the account does not exist or something like they have typed int he wrong password and username } } ?> <html lang="en"><meta charset="utf-8"><head></head><title>Login to your account!</title> <body> <center> <span style="font-size: 32px; font-weight: bold; font-family: Arial; padding; 10px;"> Please Login </span> </center> <link rel="stylesheet" href="css/login.css" /> <div class="login"> <center> <form action="" method="POST"> <br><br>Username: <br><input type="text" name="username" placeholder="Username" required /> <br><br>Paswsord: <br><input type="password" name="password" placeholder="Password" required /> <br><br><input type="submit" name="submit" value="Login to your account!" /> </center> </div> </form> </body> </html> It says wrong password Like I said below the reviison I made. If you use this, you'll need to redo your whole password algorithm. You'll have to start using password_hash and password_verify. You need to change your old passwords to the new passwords. Basically, backup your whole users table and then drop the users table so that you have no records in it. Then you'll have to edit the sign up page too since you're going to be using the password_hash function. Once you get the sign up page working with the password_hash function, then you can sign up with the same username and password like how you had it before. Once that is completed, you can test the login page. It should work since you are moving from a hash algorithm that isn't really a password algorithm to a built-in password algorithm. EDIT: Also, since I went back and looked at the one you modified. You're not doing it right. You don't hash the password on the login page. The only reason why you should be using the password_hash function is if you are inserting it into the database. If you want to compare the two passwords so that they match, you need to use password_verify. Edited March 15, 2015 by JustThatGuy Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.