This question already has answers here:
How to check username and password matches the database values
(3 answers)
Closed 11 months ago.
I'm trying to check if a users entered username and password matches an entry from the database using PDO, but for some reason cannot seem to get it working.
The database table is called user_info and the rows from which i'm trying to grab the username and password from are username and pass respectively. I'm not entirely sure how to check if the users input information matches a database entry, then make a decision on where to send them based on if it returns true or false.
Also, i've obviously got the prerequisites such as including a file that connects to the database, which i know whose information is correct.
I've had a stab in the dark on the if ($username) etc, but clearly it's incorrect.
HTML
<form method="post">
<label for="username2">Username</label>
<input type="text" name="username">
<label for="password">Password</label>
<input type="text" name="password">
<input type="submit" value="Login" name="login">
</form>
PHP
$username = $_POST['username'];
$password = $_POST['password'];
try {
$result = $db->prepare("SELECT * FROM user_info WHERE username = :user AND pass = :pass");
$result->bindParam(':user', $username);
$result->bindParam(':pass', $password);
$result->execute();
$rows = $result->fetch(PDO::FETCH_NUM);
}
catch (Exception $e) {
echo "Could not retrieve data from database";
exit();
}
if ($username == "test" && $password == "test") {
$_SESSION['username'] = $username;
redirect('/add-property.php');
} else {
if (isset($_POST['login'])) {
echo "Username or password incorrect";
}
}
What you can do is look up the user in the database and then return row from the query. After you compare the password that was given by the user to authenticate and the one that the query returned then return them to where they need to go.
To find your bug, add this code instead of the catch in your code:
catch (PDOException $e) {
echo "Could not retrieve data from database ".$e->getMessage;
exit();
}
You can also get your query sting to make sure it is correct like this:
echo $db->queryString;
It seems that ($username == $rows && $password == $rows) is all i needed to change in the code to correctly authenticate the username and password.
Related
I'm trying to get a login page to work with PHP and Mysql. I've combed through my code, and don't know where I'm going wrong.
First I have a "login.php" page. Here's (what I believe) is the important code on that page:
<form id="login" action="redirect.php" method="post"> <!--This is the form for logging in.-->
<fieldset id="inputs">
<input type="hidden" name="ac" value="log"> <!--This value is a "random" value to post so that an if statement will be entered in select.php-->
<input id="username" name="username" type="text" placeholder="Username" autofocus required>
<input id="password" name="password" type="password" placeholder="Password" required>
</fieldset>
<fieldset id="actions">
<input type="submit" id="submit" value="Log in">
</fieldset>
From there you'll see that when submit is pressed it goes to "redirect.php" which has the following code:
<?php
include 'config.php';
$username = $_POST['username'];
$password = $_POST['password'];
function SignIn()
{
session_start(); //starting the session for user profile page
if(!empty($username)) //check to see if the username is empty or not from login.php
{
$query = mysqli_query($con, "SELECT * FROM employees where username = ".$username." AND password = ".$password) or die(mysql_error());
$row = mysqli_fetch_array($query) or die(mysql_error());
if(!empty($row['username']) AND !empty($row['password']))
{
$_SESSION['username'] = $row['password'];
echo "SUCCESSFULLY LOGGED IN!";
}
else
{
echo "YOU ENTERED WRONG ID OR PASSWORD...";
}
}
}
if(isset($_POST['submit']))
{
SignIn();
}
?>
You'll notice the config.php page is included... Here's the code for that (with my dbusername and dbpassword changed:
<?php
/* Database credentials. */
define('DB_SERVER', 'localhost');
define('DB_USERNAME', 'myusername');
define('DB_PASSWORD', 'mypassword');
define('DB_NAME', 'ropepart_techportal');
/* Attempt to connect to MySQL database */
$con = mysqli_connect(DB_SERVER, DB_USERNAME, DB_PASSWORD, DB_NAME);
// Check connection
if($con === false){
die("ERROR: Could not connect. " . mysqli_connect_error());
}
?>
When I run through all of this on my webpage, I am greeted with a blank white page on the redirect.php. This is the case no matter what username/password combo I put in the login.php page. Whether or not the user actually exists in the database or not. I would expect to get at least a sentence at the top of the page that either says "SUCCESSFULLY LOGGED IN!" or "YOU ENTERED WRONG ID OR PASSWORD." Any idea where I'm going wrong?
You're not sending value for submit in post body.
Try adding :
<input type="submit" name="submit" id="submit" value="Log in">
Since you've checked isset($_POST['submit']) which since you're not sending evaluates to false , and SignIn() is never called
I agree with our friend here, you set id for input, but you need set name to be send during the request, but I strong recomend u change two things in your code
add this attr to input submit -> name="submit"
Instead of this
if(isset($_POST['submit']))
{
SignIn();
}
Use this
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
SignIn();
}
And don't do this on start of the code
$username = $_POST['username'];
$password = $_POST['password'];
Because when u try to access an array that is not defined the php can outputs an error, and for some security reasons this isn't recommend, so before set the variables, check it, like this:
if (isset($_POST['username']) {
$username = $_POST['username'];
}
Your intimidate problem is there is no scope resolution on your variables
$username = $_POST['username'];
$password = $_POST['password'];
function SignIn(){
//$username does not exist in this scope
Instead
function SignIn($username, $passwrd){
....
}
SignIn($username, $passwrd);
That said their is a bunch of other "stuff" that I would fix, give me a few minutes and I will post something on it. Now if you had error reporting on you would see something like this
Warning: undefined variable $username
Here you go (untested but it should be close)
<?php
//turn on error reporting for development
//note even this may not catch syntax errors if they happen in this file
error_reporting(-1);
ini_set('display_errors',1);
require_once 'config.php'; //should be require once for a config
session_start(); //starting the session for user profile page
$dashboard = 'http://localhost/dashboard'; //some location to send a user after login
if(!empty($_SESSION['username'])){
//user is already logged in
header('Location: '.$dashboard);
}
//array for error tracking
$errors = [];
//if(isset($_POST['submit']))
//by checking the below outside of this we are assuming post
// has already happend, so there is no need to check this
//it was similar in your original code.
//if post isn't set then username and password will be FALSE
//and it will be caught by the error checking for those anyway
$username = isset($_POST['username']) $_POST['username'] : false; //check if isset if not set a default
if(!$username) $errors[] = 'Please enter a username';
$password = isset($_POST['password']) $_POST['password'] : false;
if(!$password) $errors[] = 'Please enter a password';
if(count($errors)){
//return to the page with error messages
//I have no idea how you build the page or how it relates to this
//so I cant hellp you there
die(implode('<br>', $errors));
}else{
//use single quotes for SQL, which prevents accidentally putting a variable in it.
// '$password' is literally $password, but "$password" is the value of it
//look up only what you need (password)
//don't look up by the password, DB is case insensitive and
//and is not cryptologicalally secure way to compare hashes.
$stmt = mysqli_prepare($con, 'SELECT password FROM employees where username = ?');
//I don't use mysqli (for like 4 years, and I never used the procedural style)
//so I had to look this up, if it's not right sorry ;-/, this is so much harder then PDO
/* bind parameters for markers */
mysqli_stmt_bind_param($stmt, "s", $user);
/* execute query */
mysqli_stmt_execute($stmt);
/* bind result variables */
mysqli_stmt_bind_result($stmt, $hash);
//not sure this will work, sorry
//in the example it showed storing the results,
//so not sure if you have to do that.
$num_rows = mysqli_stmt_num_rows($stmt);
//check that one and only one row is returned
if(!$num_rows){
//User not found, again I have no idea how to display this for you
die('Username was incorrect, please try again.');
}else if($num_rows > 1){
//should never happen with unique usernames
// again I have no idea how to display this for you
//this can prevent some errors from allowing logins
//this is an error message you may not want to show in production code
die('Returned more then one user account.');
}
/* fetch value */
//because we did mysqli_stmt_bind_result($stmt, $hash)
//which is bind $hash to column 1, this populates that
//variable with the data from the first row
mysqli_stmt_fetch($stmt);
//bool password_verify ( string $password , string $hash )
//Aug1 $password is plaintext, Arg2 $hash is from the DB
if(password_verfy($password, $hash)){
$_SESSION['username'] = $row['username'];
//you had password here in your original code (another bug?)
//$_SESSION['username'] = $row['password'];
//user is already logged in
header('Location: '.$dashboard);
}else{
//Incorrect password, again I have no idea how to display this for you
die('Your password was incorrect, please try again.');
}
}
I ditched the function call, as you mentioned in the comments.
I decided to get rid of my SignIn() function entirely, as it seems to not be needed in this case
You can read about prepared statements here
http://php.net/manual/en/mysqli.prepare.php
As I mentioned in the code, I haven't used mysqli much in the last 4 years, and even then I never used the procedural style. I quit doing the procedural style when I switched from mysql to mysqli about 7 years ago. There may be better ways to do that in mysqli, I just copied the example on the PHP documentation site. With PDO it would just be this (which is so much more elegant):
$stmt = $PDO->prepare('SELECT * FROM employees where username = :username');
$stmt->execute([':username' => $username]);
$num_rows = $stmt->rowCount();
$pass = $stmt->fetchColumn(0);
And the above assumes you are using PHP's built in password functions, which you should.
So to create a password use password_hash.
http://php.net/manual/en/function.password-hash.php
And to check it use password_verfy.
http://php.net/manual/en/function.password-verify.php
SQL Injection
In your original code we could turn you query into this,
"SELECT * FROM employees where username = ".$_POST['username']." AND password = ".$_POST[password]"
This is equivalent to what you have. Without preparing it someone can enter " OR 1=1 in the password field. There are only 2 styles of quotes and it wouldn't take much to figure it out. You can also encode the quotes in some instances, so simply checking for quotes wont due. What this would do is make your query:
SELECT * FROM employees where username = "admin" AND password = "" OR 1=1
Now because 1 is always equal to one 1 and this is password OR 1 then it effectively bypasses the password. You should only pull the password from the DB and then check it in PHP. That would prevent all of this (even with the sql issues) because as an attacker I would still need the password to pass that check. For example.
SELECT password FROM employees where username = "" OR 1=1
...
//even with a hacked row from the DB I still don't have $_POST['password']
if($_POST['password'] == $row['password'])
A few other Attacks
For the username it's almost the same " OR 1=1 --. The -- is the start of a line comment in SQL. And, because you are not checking the number of returned results it would also log me in as probably the first user found.
SELECT * FROM employees where username = "" OR 1=1 -- AND password = "
However if even if you did (check the number of results) all I would need to add is LIMIT 1 " OR 1=1 LIMIT 1 -- to it. I would probably do it this way anyway, if I was a hacker.
SELECT * FROM employees where username = "" OR 1=1 LIMIT 1 -- AND password = "
Then to boot I could iterate thought all your users by using an offset.
SELECT * FROM employees where username = "" OR 1=1 LIMIT 0, 1 -- AND password = "
SELECT * FROM employees where username = "" OR 1=1 LIMIT 1, 1 -- AND password = "
SELECT * FROM employees where username = "" OR 1=1 LIMIT 2, 1 -- AND password = "
etc.
And then steal all their stuff, or pick one with administrative rights your site etc.
Problem with not encrypting passwords
One of the biggest problems (outside of the obvious ones) is that users are lazy and they tend to use the same passwords. So once I compromised and admin account or even if you show the old password when a user goes to change it. Whatever way I get it... I could try that password against their email, also in their account. And once I find the poor sucker that has the same email password, I could find any sites they use. Then use that common password (preferred as they wont even know) or now that I own their email account I can just reset the password if I need to, to gain access to things like their online banking accounts etc..
So as you can see this is not something we can allow to happen.
Even when just learning, we should try to learn to do it the proper way, or at least in a way that offers some minimal security.
Cheers.
Why didn't the other posts help?
Other posts didn't help because one was asking since none worked, despite there are a lot of similar questions.
More details
The thing I want to do is to make a user log in using his password. But, the passwords are hashed using bCrypt in the database.
When I try to enter the real password, it doesn't work and says that the password is incorrect.
But, when I try to enter the hashed password. It says: "Successfully logged in".
How to make it log in using the real password not the hash?!
Code
Login.php
<form method="post" action="loginsession.php">//login
<p>Username <input type="text" name="uid" size="20"> </p>
<p>Password <input type="password" name="pwd" size="20"> </p>
<p><input type="submit" value="Login" name="login"></p>
</form>
Loginsession.php
<?php
session_start();
include ('dbhandler.php');
$uid = $_POST['uid'];
$pwd = $_POST['pwd'];
$sql = "SELECT * FROM user WHERE uid='$uid' and pwd='$pwd' ";
$result = mysqli_query($conn, $sql);
$row = mysqli_fetch_assoc($result);
$encrypted_pwd = password_hash($pwd, PASSWORD_DEFAULT);
$hash = password_verify($pwd,$encrypted_pwd);
$count = mysqli_num_rows($result);
if ($count == 1) {
echo("Logging in...");
$_SESSION['id'] = $row['id'];
$_SESSION['uid'] = $row['uid'];
$_SESSION['pwd'] = $row['pwd'];
echo("<h1 style='color:green;'>Successfully Logged In");
}
else {
echo "Your Login Name or Password is invalid";
die();
}
?>
There was so much wrong that a rewrite was more appropriate:
<?php
session_start();
include 'dbhandler.php'; // shouldn't be include './dbhandler.php'; ?
$uid = $_POST['uid'];
$pwd = $_POST['pwd'];
$sql = "SELECT * FROM user WHERE uid='".mysqli_real_escape_string($conn, $uid)."'";
$result = mysqli_query($conn, $sql);
if (mysqli_num_rows($result) === 1) {
$row = mysqli_fetch_assoc($result);
if (password_verify($pwd, $row['pwd'])) {
$_SESSION['id'] = $row['id'];
$_SESSION['uid'] = $row['uid'];
$_SESSION['pwd'] = $row['pwd'];
// redirect to "login success" page would be a better solution
echo "<h1 style='color:green;'>Successfully Logged In";
} else {
echo "Invalid password";
}
} else {
echo "Your login name is invalid";
}
You should never use textual user input as a parameter of your query. This leaves you vulnerable to SQL injection. To prevent that, either use PDO or mysqli_* (but in this case use the appropriate functions to escape the parameters), which are both well documented.
You define and execute the query with passing the password as it was. You need to hash the password BEFORE you pass it to the query and pass $encrypted_pwd to the query.
I recommend the usage of limit 0, 1 at the end of your query in this case, as that will specify that you are interested only in the very first corresponding row, if exists, so the query will be stopped if the user is found and not continue searching for users. This will optimize your query.
Since you do not want to load any particular data related to the user, you only want to find out whether the user exists, you could further optimize your query by replacing select * with select 1, which will significantly reduce the size of data your RDBMS will have to send in response, as only a number will be returned and not the whole record, possibly with the user's biography.
Never ever store a user's password in the session. If for some reason $_SESSION will be outputted to the browser, that will be a serious vulnerability.
I am having a pig of a time with my code. I am new to this and am struggling greatly.
I have several issues, firstly one problem is that I am trying to use a login form which is connected to an SQL database, but do not get an error when incorrect data or no data is entered, but it looks to log in.
Secondly, I am trying to show the username on each page when users are logged in, which works, but only for those users that have been manually entered into the database. Any user that has been added via my registration form, do not show, though they are showing in phpmyadmin.
My login page code for the first problem is:
<?php
echo '<h3>Sign in</h3>';
if($_SERVER['REQUEST_METHOD'] != 'POST')
{
/*the form hasn't been posted yet, display it
note that the action="" will cause the form to post to the same page it is on */
echo '<form method="post" action="">
Username: <input type="text" name="Username" />
Password: <input type="password" name="Password" />
<input type="submit" value="Sign in" />
</form>';
}
else
{
//the form has been posted without errors, so save it
//notice the use of mysql_real_escape_string, keep everything safe!
$username = mysql_real_escape_string($_POST['Username']);
$password = mysql_real_escape_string($_POST['Password']);
$sql = "SELECT * FROM Users WHERE Username = '$username' AND Password = '$password'";
$result = mysql_query($sql);
if(!$result)
{
//something went wrong, display the error
echo 'Something went wrong while signing in. Please try again later.';
header("location:index.php");
//echo mysql_error(); //debugging purposes, uncomment when needed
}
else
{
{
{
//set the $_SESSION['signed_in'] variable to TRUE
$_SESSION['signed_in'] = true;
//we also put the user_id and user_name values in the $_SESSION, so we can use it at various pages
while($row = mysql_fetch_assoc($result))
{
$_SESSION['UserID'] = $row['UserID'];
$_SESSION['Username'] = $row['Username'];
}
echo 'Welcome, ' . $_SESSION['Username'] . ' Proceed to the forum Home page.';
}
}
}
}
?>
Thanks for any advice.
Function mysql_query() returns FALSE when there is an actual mysql error. That can be syntax error, invalid constraint insert or input datatype mismatch. If any inserted username and password combination can potentially be valid, that means there won't be any errors.
In your case, if username or password are wrong, it means that 0 rows (no data) is returned which is not an error. So in your code, variable $result is never FALSE, and that is why your code never goes in error loop.
In order to fix this, you will need to change your code to check if number of returned rows is greater than 0 rather than checking if result is TRUE. You can achieve this by using mysql_num_rows() function.Changed code should look like this
$result = mysql_query($sql);
$num_rows = mysql_num_rows($result);
if($num_rows < 0){
//put some code for error
}
Further notes : If you don't want to use PDO you can use mysqli instead of mysql. Also you are vulnerable to sql injection. It would be really good if you take a look at prepared statements and how to make data coming to your server more secure.
I'm a beginner in the programming field..
My concept is just to move,to the home page from the login page after doing the checking of user id and password. i have a database table with fields 'user_id' & 'password'. so i want to get the datas from the table to array and then want to compare it with the values entered by the user...How is it possible in the most easiest way?
I always use
$query = "...";
$sql = mysql_query($query);
while($row = mysql_fetch_assoc($sql)) {
$user_id = $row['user_id'];
// ...
}
I think that should work better as you get an associative array, so you can work with the field names.
Note that if you're selecting SUM(*), you have to put $row['SUM(*)'] or give it a name via SQL.
Although you've shown little research and your question is quite broad, I'll show you an example that might give you some clues.
$username = mysql_real_escape_string($_POST['username']); //escaping the string, will use it in a query
$password = $_POST['password'];
$result = mysql_query("SELECT password FROM users WHERE username = '$username'");
if (mysql_num_rows($result) == 1) { // Expecting one result
$userdata = mysql_fetch_array($result);
if ($password == $userdata['password']) {
// USER IS AUTHORISED
} else {
// USER IS NOT AUTHORISED
}
}
This is a simple example.
Things to consider:
Although I did that in the example above to simplify things, do not store password as plaintext in the database - store a MD5 hash instead. You can generate a hash by using md5("string to hash"). If you need help with that start another question.
After you have authorised the user you can "remember" that by using PHP sessions. Again, if you need help with that ask another question.
$username="username";
$password="password";
//Specify MySQL database to connect to
$database="database";
//Create connection and select the appropriate database
mysql_connect("localhost",$username,$password);
#mysql_select_db($database) or die( "Unable to select database");
//Get the username and password from posted form
$username = mysql_real_escape_string($_POST['username']);
$password = mysql_real_escape_string($_POST['password']);
//Build the query to look for users that exist with that username/password combination
//Here I'm using the users table within my database
$query = "SELECT * FROM users where username=\"$username\" and password = \"$password\" ";
//Retrieve the results of the query, and also aquire the number of records returned
$result = mysql_query($query);
$num = mysql_numrows($result);
//Check to see how many records are returned
if ($num>0)
{
//User login was successful
echo 'success login';
} else {
//Login was unsuccessful
echo 'user name not found';
}
Try this
//HTML
<form method="post">
<input type="text" name="username" />
<input type="password" name="password" />
<input type="submit" name="login" value="login"/>
</form>
//PHP
if(isset($_POST['login']))
{
$username=$_POST['username'];
$password=$_POST['password'];
$username=mysql_real_escape_string($username);
$password=mysql_real_escape_string($password);
$query = "select username,password from tableName
where username='$username' and password='$password'";
$sql = mysql_query($query);
if(mysql_num_rows($sql) == 1)
{
// Login success save username in session redirect to homepage
header("location:homepage.php");
exit();
}
else
{
// Display error message
}
}
Well, I am working on a new project which has a login page. The Error: I am unable to retrieve password from the form using $_POST method.
The Form Code:
<form action="loginsub.php" method="post">
<input type="password" name="pass" id="pass"/><br/>
<input type="submit" value="Go!"/>
</form>
The Code in loginsub.php
<? echo $_POST['pass']; ?>
I have also tried this method using text in place of password and it works. But what is the problem with the password? When I fill in the form and then submit it, the next page displays nothing!
Okay, Now, It's working! Thank you all, The Real Problem was: I want to take in password from a login form and then using mysql_query (php) want to find out if the username and password combination is there or not. If I am not wrong, the code for it is:
require_once('dbconfig.php');
$username = $_POST['username'];
$pass = $_POST['pass'];
$dbc = mysql_connect($dbserver,$dbuser,$dbpassword);
mysql_select_db('hello');
$query = "SELECT * FROM users WHERE username = '$username' AND password = PASSWORD('$pass')";
$result = mysql_query($query);
$row = mysql_num_rows($result);
if ($row == 1)
{ echo "User Name and Password are Correct"; }
else
{ echo "Error! Username and Password is Wrong!"; }
Is the code right? When I execute it, enter correct username and password (which exists in the database, I get the InCorrect Message, but again when I enter wrong username and password, I still get InCorrect message. Why?
I take you don't really want to print the password in your application? Anyway, it should be in your $_POST array - could you paste the output of putting
var_dump( $_POST );
in the page your submitting to?