I'm trying to has a password in PHP using password_hash and password_verify. I am correctly hashing the password as it is being into the database hashed, but when I attempt to unhash the password whilst logging in, it doesn't seem to want to work. The password is being recieved from an Android application but after echoing both the username and the password, they are correct to what they should be. To hash the password, I am using PASSWORD_DEFAULT as the hashing technique.
Code:
<?php
error_reporting(0);
require_once('dbconnect.php');
$username = $_POST["username"];
$password = $_POST["password"];
$result = $conn->query("SELECT * FROM User WHERE username ='$username'");
if(empty($result)){
die("Username doesn't exist");
}
$dbpass = $conn->query("SELECT password FROM User WHERE username = '$username'");
if (password_verify($password, $dbpass)){
$stmt = "SELECT * FROM User WHERE username='$username' and password='$password'";
$check = mysqli_fetch_array(mysqli_query($conn, $stmt));
if(isset($check)){
echo "success";
}else{
echo "Invalid Username or Password";
}
}
else {
echo "password not unhashing";
}
$conn->close();
Am I missing something obvious?
First, use prepared statements to remove the threat of SQL injection, or your login screen becomes an attack vector. Then the problem is you're not getting the actual dbpass, you're getting a result set containing $dbpass, without dereferencing it.
Try it this way:
//username in where clause is coming from the user, don't execute it
//also fetch a clean copy of the username from the database we can trust to do things with like display -- assuming we filtered it on the way into the database.
$stmnt = $conn->prepare('select username,password from user where username = ?') or die('...');
//username must be a string, and to keep it clear it came from a user, and we don't trust it, leave it in POST.
$stmnt->bind_param('s',$_POST['username']) or die('...');
//Do the query.
$stmnt->execute() or die('...');
//Where to put the results.
$stmnt->bind_result($username,$dbpass);
//Fetch the results
if($stmnt->fetch()) //get the result of the query.
{
if(password_verify($_POST['password'],$dbpass))
{
//The password matches.
}
else
{
//password doesn't match.
}
}
else
{
//username is wrong.
}
Related
I am in the process of creating a signup system using mysql and PHP. I have been able to connect the system to a database and it works for when the username and password entered are correct. However, when the username and password is not correct (i.e anytime when the username/password pair is not stored in the database), it just leads to a blank white page. Currently, my code has it so that when the username and password are not correct, it prints our "Invalid username of password". Please see the code below, any help is appreciated. Thank you in advance!
<?php
require_once 'source/session.php';
require_once 'source/db_connect.php';
if(isset($_POST['login-btn'])) {
$user = $_POST['user-name'];
$password = $_POST['user-pass'];
try {
$SQLQuery = "SELECT * FROM users WHERE username = :username";
$statement = $conn->prepare($SQLQuery);
$statement->execute(array(':username' => $user));
while($row = $statement->fetch()) {
$id = $row['id'];
$hashed_password = $row['password'];
$username = $row['username'];
if(password_verify($password, $hashed_password)) {
$_SESSION['id'] = $id;
$_SESSION['username'] = $username;
header('location: dashboard.php');
}
else {
echo "Error: Invalid username or password";
}
}
}
catch (PDOException $e) {
echo "Error: " . $e->getMessage();
}
}
?>
Well, currently your SQL query would return a set with 0 rows for a non-existent user, but that would not cause an error. It would just be an empty result set. Therefore it would not go through the while loop, it would just terminate without an error.
Your logic is leaving out the check to see whether $statement->rowCount() is zero.
To clarify in case this answer is confusing: You have 0 results if you enter a username that doesn't exist... then you do while(0) so you never get into that part of the code. No password check is done. And no error is thrown, so you never escape the try{} and get into the catch{} portion of the code. There is nothing returned here if the username turns up zero results from the database. You need to add another error in that case.
my login activity cannot read encrypted Password i tried without encrypted password and it works and im not sure if the error from php or activity itself of how to decryption password
im Using PASSWORD_BCRYPT
<?php
include "conn.php";
$Email = $_POST['Email'];
$Password = $_POST['Password'];
$sql_login = "SELECT * FROM users WHERE Email = :EMAIL and Password =:PASSWORD";
$stmt = $PDO->prepare($sql_login);
$stmt->bindParam(':EMAIL', $Email);
$stmt->bindParam(':PASSWORD', $Password);
$stmt->execute();
if ($stmt->rowCount() > 0) {
$returnApp = array('LOGIN' => 'SUCCESS');
echo json_encode($returnApp);
}else{
$returnApp = array( 'LOGIN' => 'FAILED');
echo json_encode($returnApp);
}
?>
To correctly use hashing of a password in PHP, use the password_hash and password_verify combination.
When a user signs up, you get his password, hash it and store it in the database:
$hash = password_hash($_POST['newpassword'], PASSWORD_DEFAULT);
// store $hash in database column "password"
When this user wants to login, you check against the hash:
// fetch hash from database, store it in $stored_hash
$logged_in = password_verify($_POST['password'], $stored_hash);
if ($logged_in === TRUE) {
echo "Welcome!";
} else {
echo "Username or password incorrect.";
}
Final notes:
Use PASSWORD_DEFAULT and make sure your database can store the result (also in the future). Hashing algorithms happen to get cracked once in a while.
You could use another provider like Google or Facebook to handle your authentication. This does have its drawbacks as well though.
I am using password_hash function, it work's well in registration form and login form but doesn't work during change password form, it gives me error message incorrect old password may be my code has gone wrong or may be because password_hash generates different set of characters each time even with the same input, if it is so what method is used to update password. the same code works using md5.
if(isset($_POST['senddata'])){
$old_password = $_POST['oldpassword'];
$new_password = $_POST['newpassword'];
$repeat_password = $_POST['newpassword2'];
$query = $db->prepare("SELECT * FROM users WHERE username=:username");
$query->execute(array(':username'=>$username));
$row = $query->fetch(PDO::FETCH_ASSOC);
$db_password=$row['password'];
// hash old password before match
$old_password = password_hash($old_password, PASSWORD_DEFAULT);
// check if old password equals db_password
if ($old_password==$db_password) {
// continue changing users password
if ($new_password==$repeat_password) {
// hash the new password
$new_password=password_hash($new_password, PASSWORD_DEFAULT);
$repeat_password=password_hash($repeat_password, PASSWORD_DEFAULT);
// update password
$password_update_query=$db->prepare("UPDATE userss SET password=:password, password2=:password2 WHERE username=:username");
$password_update_query->execute(array(':password'=>$new_password,':password2'=>$repeat_password2,':username'=>$username));
echo "Your Password Updated";
}
} else {
echo "Old password is incorrect";
}
}
You need to use password_verify($password, $hash); for verifying that passwords are equal
When you hash it again you get a other result because it generates a new salt, which then result in an other hash.
Something like:
$old_password = $_POST['oldpassword'];
$db_password = $row['password']; // which should be already hashed
if (password_verify($old_password, $db_password) {
I have a website that I need users to be able to login to. It is currently on a different server from the company's actual website. I would like to have a single login form that checks for a username and password in multiple databases on the same server.
Heres the setup.
1 Database has 2 different tables that I need to check for username and password.
the other database has 1 table that I need to check.
I will have a checkbox for 1 of the tables in the first database. So the form will have 3 field. (Username, Password, and "I am a reporter" checkbox)
I believe that it has something to do with the UNION sql command.
I don't know a LOT about sql but I am trying to learn as I go...
Here is the code so far.. also, I hope someone will tell me whether the information will be passed securely or not.
<?php
session_start(); // Starting Session
$error=''; // Variable To Store Error Message
if (isset($_POST['submit'])) {
if (empty($_POST['uname']) || empty($_POST['pswd'])) {
$error = "Username or Password is invalid";
}
else
{
// Define $username and $password
$uname=$_POST['uname'];
$pswd=$_POST['pswd'];
// Establishing Connection with Server by passing server_name, user_id and password as a parameter
$con = mysql_connect("10.0.0.3", "webaccess", "ccrweb");
// To protect MySQL injection for Security purpose
$username = stripslashes($username);
$password = stripslashes($password);
$username = mysql_real_escape_string($username);
$password = mysql_real_escape_string($password);
// Selecting Database
$db = mysql_select_db("company", $connection);
// SQL query to fetch information of registerd users and finds user match.
$query = mysql_query("select * from dbo.contacts where WebPwd='$password' AND WebAcctName='$username'", $connection);
$rows = mysql_num_rows($query);
if ($rows == 1) {
$_SESSION['login_user']=$username; // Initializing Session
header("location: "); // Redirecting To Other Page
} else {
$error = "Username or Password is invalid";
}
mysql_close($connection); // Closing Connection
}
}
?>
It is not all complete yet and I am still researching but I am also trying to do this as quick as possible.
any help will be greatly appreciated!
It appears you make a connection declaring one name and then a different connection object name later.
$con = mysql_connect("10.0.0.3", "webaccess", "ccrweb");
$db = mysql_select_db("company", $connection);
I believe the later should use the same name $con and also at the end mysql_close($con);
First, you should use the mysqli_ or PDO API instead of mysql statements
If you need to use mysql, here is what to do:
$QueryReporter = mysql_query("SELECT * FROM $ReporterTable WHERE Username = '$Username' AND Password = '$Password'");
$QueryOthers = mysql_query("SELECT * FROM $UserTable WHERE Username ='$Username' AND Password = '$Password'");
if(mysql_num_rows($QueryReporter)==1){
//Its a reporter
}
else if(mysql_num_rows($QueryOthers)==1){
//Its not a reporter, but a user
}
else{
//Its no user or reporter, show error :)
}
EDIT:
If you are thinking about two different DB servers, you can use a function, then close the connection after the full query and return the result:
function CheckIfReporter($Username, $Password){
//DATABASE CONNECTION TO REPORTER DB
$Query = mysql_query("SELECT * FROM MyTable WHERE Username = '$Username' AND Password = '$Password'");
if(mysql_num_rows($Query)==1){
return TRUE;
}
//Else, no result:
else{
return FALSE;
}
//Close mysqlconnection:
mysql_close();
}
Now, make a similar function for user check,
if(CheckIfReporter($UsernameInput, $PasswordInput)==TRUE){
//Its a reporter
}
else if(CheckIfUser($UsernameInput, $PasswordInput)==TRUE){
//Its a user
}
else{
//Its none
}
I'm trying to create passwords that are sha256 hashed with a $salt variable to it. But for some reason it just won't work. Been working 3 hours on this now, and I'm about to rip my head off. Here is my code:
I'll try again, sorry ;o)
Ok, my script worked fine, untill I tried to add the sha256 to the passwords. I got a file for creating users which is:
$salt = "lollol";
$password = hash('sha256', $salt.$_POST['password']);
$sql = ("INSERT INTO members (username, password, name, last_name,company)VALUES('$username', '$password', '$name', '$last_name', '$company')")or die(mysql_error());
if(mysql_query($sql))
echo "Your accuont has been created.";
It seems like it's correctly added to the Database. I can see that it is getting hashed with some letters and numbers.
But then when I'm trying to login, it just won't.
My code for login.php is:
$sql= "SELECT * FROM members WHERE username='$username' and password='$password'";
$result=mysql_query($sql);
$row=mysql_fetch_array($result);
$username = mysql_real_escape_string($_POST['username']);
$password = $_POST['password'];
$salt = "lollol";
$auth_user = hash('sha256', $salt.$password);
if($password == $salt.$auth_user){
echo "Logged in";
} else {
echo "Not logged in";
}
I got the idea of that, I have to encrypt password when I want to log in, but im not sure. I hope that some of you can help me.
When trying to login you concatenate the hash with the salt once more
$auth_user = hash('sha256', $salt.$password);
if($password == $salt.$auth_user){ // <-- $salt once more
echo "Logged in";
} else {
echo "Not logged in";
}
It should work, if you just remove it
$auth_user = hash('sha256', $salt.$password);
if($password == $auth_user){
echo "Logged in";
} else {
echo "Not logged in";
}
Update: Going further
here
$sql= "SELECT * FROM members WHERE username='$username' and password='$password'";
You try to retrieve the row, where the username matches $username and the password matches $password. In the database the passwords are already hashed (and $password seems to be not defined at all), thus this query will never return any row.
$password = hash('sha256', $salt.$_POST['password']);
$username = mysql_real_escape_string($_POST['username']);
$sql= "SELECT * FROM members WHERE username='$username' and password='$password'";
$result=mysql_query($sql);
$result should now contain the only user that matches the given credentials. Its now very easy
if (mysql_num_rows($result) === 1) {
echo "Logged in";
} else {
echo "Not logged in";
}
You're storing an encrypted password, but your select query is looking for the unencrypted password.
Just get the matching username (without a password condition) - usernames are unique, right?:
$sql= "SELECT * FROM members WHERE username='$username'";
$result=mysql_query($sql);
$row=mysql_fetch_array($result);
$username = mysql_real_escape_string($_POST['username']);
$password = $_POST['password'];
$salt = "lollol";
$auth_user = hash('sha256', $salt.$password);
if($row["password"] == $auth_user){
echo "Logged in";
} else {
echo "Not logged in";
}
$password = $_POST['password'];
// This should be the users actual salt after you've found the user
// in the database by username or email, or other means
$salt = $users_stored_salt;
// This should be the exact method you use to salt passwords on creation
// Consider creating a functon for it, you must use the same salt
// on creation and on validation
$hashed_password = hash('sha256', $salt.$password.$salt);
// This is the user's hashed password, as stored in the database
$stored_password = $users_stored_password;
// We compare the two strings, as they should be the same if given the
// same input and hashed the same way
if ($stored_password === $hashed_password){
echo "Logged in";
} else {
echo "Not logged in";
}
Missed your edit, but hope this helps.
EDIT: I see you aren't storing unique hashes.
If you are looking up the user by password, you need to hash the password in your query the same way it was stored:
$salt = $your_salt;
$hashed_password = hash('sha256', $salt.$_POST['password']);
$sql= "SELECT * FROM members WHERE username='$username' and password='$hashed_password'";
Otherwise, you could look up by unique username (not by password) and just compare the hashed input to the value of the stored password.
I'm very confused right now. How should my login_ac.php look like, if I should make it with the code I gave you in the top?
Just change the query to lookup by hashed password (the way you stored it).
$sql= "SELECT * FROM members WHERE username='$username' and password='".hash('sha256', $salt.$_POST['password'])."'";
You can remove the other validation and hashing - if you found the user then you know the input is valid.
Note that this only works when you know the way you're hashing the input is the exact same way you hashed the password upon creation.
It is worth checking that the field length in the database is big enough to store the whole hashed password without truncating it. You will never get a password match when logging in if the stored password is has the end missing.