As I was changing my MySQLi to PDO, I encountered an error when fetching hashed strings from my users table.
This was the code I used before:
CheckPassword VERIFIES VALID USING MYSQLI
$mysqli = new mysqli("localhost","_USER_","_PASS_","_DB_");
$username = '_USERNAME_';
$pass = '_PASSWORD_';
$sql = "SELECT * FROM `users` WHERE username='$username' LIMIT 1";
$result = $mysqli->query($sql);
if($assoc = $result->fetch_assoc()){
$db_pass = $assoc['userpass'];
require 'PasswordHash.php';
$hash_cost_log2 = 8;
$hash_portable = FALSE;
$hasher = new PasswordHash($hash_cost_log2, $hash_portable);
if($hasher->CheckPassword($pass, $db_pass)) {
echo "valid"; // VERIFIES VALID
} else {
echo "invalid";
}
}
The reason why I switched to PDO was to prevent SQL Injections.
But now: CheckPassword VERIFIES INVALID USING PDO
$pdo = new PDO('mysql:dbname=_DB_;host=localhost', '_USER_', '_PASS_',
array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION));
$username = '_USERNAME_';
$pass = '_PASSWORD_';
$stmt = $pdo->prepare('SELECT * FROM `users` WHERE username = :u LIMIT 1');
$stmt->bindParam(':u', $username);
$stmt->execute();
if($fetch = $stmt->fetch(PDO::FETCH_ASSOC)){
$db_pass = $fetch['userpass'];
require 'PasswordHash.php';
$hash_cost_log2 = 8;
$hash_portable = FALSE;
$hasher = new PasswordHash($hash_cost_log2, $hash_portable);
if($hasher->CheckPassword($pass, $db_pass)) {
echo "valid";
} else {
echo "invalid"; // VERIFIES INVALID
}
}
}
How is it that; MySQLi fetches the hashed string different compared to PDO? No matter what encryption I use for hashing the passwords, it CANNOT validate them as true when fetching using PDO, BUT only when fetching using MySQLi?
The reason because when you comparing the password that the user enter and the password that in the database , its different , the pass that the user enter to log in to his account is not hashed while the one in the database is , so we need a way to hash the entered pass and validate it with the already hashed pass in the database . How to do that ? here
This is an example from a code that i use in my Control panel :
<?php
// connect to your database
if(isset($_POST['btn-login']))
{
$User_name = $_POST['userlogin'];
$password_user = $_POST['pass'];
$FetchUserData = $conn->prepare("SELECT * FROM users WHERE userlogin = ?");
$FetchUserData->execute(array($User_name));
$FetchedData = $FetchUserData->fetch(PDO::FETCH_ASSOC);
if ($FetchedData)
{
$password = $FetchedData['userpassword']; // Save the fetched password inside variable
$isPasswordCorrect = password_verify($password_user, $password);
if( $password_user == $isPasswordCorrect )
{
$_SESSION['login_user']=$User_name;
header("location: home.php");
}
else
{
echo "Password is wrong":
}
}
else
{
echo "User is not exist ";
}
}
?>
This Code line is the code used to hash the enterd pass with the exist pass in the database :
$isPasswordCorrect = password_verify($password_user, $password);
Small explanation :
password_verify(parameterA,parameterB)
parameterA : The password that you want it to be validate .
parameterB : the password that you want it to be validated with .(
database that is stored in the database )
Hope this answer be helpful for you .
Related
<?php
require "Common.php";
$player_username = $_POST ["usernamePost"];
$player_password = $_POST ["passwordPost"];
$hashed_password = password_hash($player_password, PASSWORD_DEFAULT);
$conn = new mysqli ($server_host, $server_username, $server_password, $server_dbName);
$result = mysqli_query ($conn, "SELECT * FROM users WHERE Username ='$player_username' and Password = ''");
$count = mysqli_num_rows($result);
if ($count == 1) {
while ($row = mysqli_fetch_assoc ($result)) {
if (password_verify($player_password, $hashed_password)) {
echo "Signing in...<br>";
echo "ID:".$row ['ID'] . "|Username:".$row ['Username'] . "|Score:".$row ['Score'] . "|Status:".$row ['Status'];
}
}
}
else {
echo "Incorrect username or password.";
}
?>
Second piece of code:
<?php
require "Common.php";
$player_username = $_POST ["usernamePost"];
$player_password = $_POST ["passwordPost"];
$hashed_password = password_hash($player_password, PASSWORD_DEFAULT);
$conn = new mysqli ($server_host, $server_username, $server_password, $server_dbName);
$queryCode = "SELECT * FROM users WHERE Username = '$player_username'";
$query = mysqli_query ($conn, $queryCode);
if (mysqli_num_rows($query) > 0) {
echo "Username already exists.";
} else {
$sql = "INSERT INTO users (Username, Password)
VALUES ('".$player_username."','".$hashed_password."')";
$result = mysqli_query ($conn,$sql);
echo "User created.";
}
?>
I can create an account with a hashed password, however, I cannot login with it. I've looked at every post regarding my issue on this website. It's either that I was looking at the wrong thread or I simply did not understand what they were doing.
You cannot verify a hashed password because you're select a user having a blank password:
$result = mysqli_query ($conn, "SELECT * FROM users WHERE Username ='$player_username' and Password = ''");
Remove the password test from your query:
<?php
require "Common.php";
$player_username = $_POST ["usernamePost"];
$player_password = $_POST ["passwordPost"];
$hashed_password = password_hash($player_password, PASSWORD_DEFAULT);
$conn = new mysqli ($server_host, $server_username, $server_password, $server_dbName);
$result = mysqli_query ($conn, "SELECT * FROM users WHERE Username ='$player_username'");
$count = mysqli_num_rows($result);
if ($count == 1) {
$row = mysqli_fetch_assoc ($result);
if (password_verify($player_password, $row['hashed_password'])) {
echo "Signing in...<br>";
echo "ID:".$row ['ID'] . "|Username:".$row ['Username'] . "|Score:".$row ['Score'] . "|Status:".$row ['Status'];
}
} else {
echo "Incorrect username or password.";
}
Since you're only returning one row you have too much code. No need for a while loop and you have to test against the password stored in the database $row['hashed_password'].
In addition:
Little Bobby says your script is at risk for SQL Injection Attacks. Learn about prepared statements for MySQLi. Even escaping the string is not safe! Don't believe it?
EDIT: Here is an example using a prepared statement and proper error checking:
require "Common.php";
$player_username = $_POST ["usernamePost"];
$player_password = $_POST ["passwordPost"];
$conn = new mysqli($server_host, $server_username, $server_password, $server_dbName);
/* check connection */
if (mysqli_connect_errno()) {
echo "Connect failed: ", mysqli_connect_error());
exit();
}
$stmt = $conn->prepare("SELECT * FROM users WHERE Username =?"); // prepare with a placeholder for the variable
$stmt->bind_param('s', $player_username); // bind the variable
$stmt->execute(); // execute the query
$row = $stmt->fetch_assoc(); // get the associative array
if (password_verify($player_password, $row['hashed_password'])) {
echo "Signing in...<br>";
echo "ID:".$row ['ID'] . "|Username:".$row ['Username'] . "|Score:".$row ['Score'] . "|Status:".$row ['Status'];
} else {
echo "Incorrect username or password.";
}
Keep in mind that there are a couple of methods for coding and executing prepared statements. Use the method you're most comfortable with.
From Proper Password Preparation with PHP
The password_hash() can generate some very lengthy text (the current default is 60 characters), so making the field larger now will allow for the length needed. Secondly the PHP team is adding more algorithms to the method which means the hash can and will grow. We also do not want to limit our user's ability to use the password or passphrase of their choice. It's best to leave room for the changes.
Set the password field in your database to be large, for example
`password` text DEFAULT NULL
I created a form to insert data(username & password) in sql server. the password there is already encrypted. my problem now is am I going to insert the $encrypt_pass in my parametrized query.
<?php
$pass= $_POST['pass'];
$encrypt_pass=md5($pass);
$params = array($_POST['user'], $encrypt_pass);
$server = "MELODY-PC\SQLEXPRESS";
$options = array("Database"=>"customerdb", "UID"=>"dbadmin", "PWD"=>"melodyjerah");
$conn = sqlsrv_connect($server, $options);
$sql = "SELECT * FROM accounting_login WHERE username = ? and password = ?";
$stmt = sqlsrv_query($conn, $sql, $params);
if(sqlsrv_has_rows($stmt))
{
header("Location: page_accounting.php");
}
else
{
echo "Invalid USERNAME or PASSWORD!";
}
?>
If you have php 5.5, use this
$password = password_hash($password_from_input, PASSWORD_DEFAULT); //store this in db
In login_form.php
$true = password_verify($password_from_input, $password_in_db); // returns TRUE or FALSE
You do not need salt, just a password column will do
So I'm enabling users to create accounts with a username and password. I have managed to encrypt the password when a user creates a new account using:
$hash = password_hash($password, PASSWORD_BCRYPT);
However I'm having trouble with password_verify when logging in, could someone please help me with what I have? I know it's something like this:
password_verify($password, $hash)
But I don't know how to structure it or where to add it in the code. Thanks in advance. This is what I have:
<?php
if (isset($_GET["username"]) && isset($_GET["password"]) ){
$username = $_GET["username"];
$password = $_GET["password"];
$result = login( $username, $password);
echo $result;
}
function makeSqlConnection()
{
$DB_HostName = "";
$DB_Name = "";
$DB_User = "";
$DB_Pass = "";
$con = mysql_connect($DB_HostName,$DB_User,$DB_Pass) or die(mysql_error());
mysql_select_db($DB_Name,$con) or die(mysql_error());
return $con;
}
function disconnectSqlConnection($con)
{
mysql_close($con);
}
function login($username, $password)
{
$con = makeSqlConnection();
$sql = "select * from login where username = '$username' and password = '$password';";
$res = mysql_query($sql,$con) or die(mysql_error());
$res1 = mysql_num_rows($res);
disconnectSqlConnection($con);
if ($res1 != 0) {
return 1;
}else{
return 0;
}// end else
}// end of Function
?>
The general practice is as follows:
Fetch password hash from the database where the username = the inputted username.
If rows are found, then there's a user
Now you compare the inputted password against the hash stored in the database.
I'll outline the above flow in some pseudo code for you here:
$query = SELECT password FROM users WHERE username = '$username'
$data = FETCH_THE_DATA($query);
if(password_verify($USER_INPUTTED_PASSWORD, $data['password'])) {
// password is correct
} else {
// password is in-correct
}
Notes
Stop using mysql_* functions. The library is deprecated as it's unreliable and will be removed in future releases of PHP.
You're better off using PDO or MySQLi Prepared Statements
You should always read the manual - password_verify(), it states clearly that you compare the "user inputted password" against the hashed version which is stored in your database.
Since I'm feeling good and sleepy today, I'll write a bunch of codes.
This is an example how to use PDO with prepared statement. You will have to tweak it according to your needs and you have to check if the post/get not empty as well.
I prefer to use POST request for login so this example will use POST request..
This is my user class. Which use placeholders and binding instead of passing the parameters into the query directly. This will give some protections against SQL injection attack.
class User{
private $dbh;
function __construct(){
$this->dbh = new PDO("mysql:host=".DB_SERVER.";dbname=".DB_NAME.';charset=utf8mb4', DB_USER, DB_PASSWORD) or die('db connect error');
}
function create($username, $password){
$status = false;
try{
$stmt = "INSERT INTO login (username, password)
VALUES (?, ?)";
$qry = $this->dbh->prepare($stmt);
$qry->bindParam(1, $username);
$qry->bindParam(2, $password);
$status = $qry->execute();
}catch(PDOException $e){
$e->getMessage();
}
$qry->closeCursor();
return $status;
}
public function getPassword($username){
$status = false;
try{
$stmt = "SELECT * FROM login WHERE username = ? LIMIT 1";
$qry = $this->dbh->prepare($stmt);
$qry->bindParam(1, $username);
$qry->execute();
$status = $qry->fetch(PDO::FETCH_ASSOC);
}catch(PDOException $e){
$e->getMessage();
}
$qry->closeCursor();
return $status;
}
}
This is how to create the user. Note that I don't check if the username already exist. You can either implement it yourself or use unique index on username column provided that the collation is case insensitive.
I have also increased the cost from the default that is 10 and I defined PASSWORD_DEFAULT to be used because I want the PHP engine to always use the strongest available algorithm (currently bcrypt).
function hashPassword($password){
$password = password_hash($password, PASSWORD_DEFAULT,array('cost' => 16));
return $password;
}
$user = new User;
$_POST['password'] = hashPassword($_POST['password']);
if(!$user->create(trim($_POST['username']),$_POST['password'])){
echo 'Failed creating user';
}else{
echo 'User created';
}
This is how to verify the password.
$user = new User;
$getPassword = $user->getPassword(trim($_POST['username']));
if(!$getPassword){
echo 'Error fetching user';
}else{
if(!password_verify($_POST['password'], $getPassword['password'])){
echo 'Login failed';
}else{
echo 'Login successful';
}
}
im new at programing and php, and i want to create an error on my registration system that when the user creates an account with the same username already existing in the database it says something like this: "Username already in use" and then if it isnt an existing username it says "Registation Complete"
I tried this code:
<?
require ("conect.php");
$user = $_POST['user'];
$pass = $_POST['password'];
$email = $_POST['email'];
$email_check = $_POST['email_check'];
$register = mysql_fetch_array;
if($user = $register[user]) {
echo"Username already in use";
}
else
{
$insert = mysql_query("INSERT INTO registration (user, password, email)
VALUES('$_POST[user]','$_POST[password]','$_POST[email]')");
echo "The account $user was successfully created.";
}
?>
But it didnt work, can someone help please
As pointed out by the other users, you should be using prepared statements through PDO (or mysqli, but I definitely prefer PDO)
You're storing the POSTS in variables, but then in the database query you are just using the $_POST variable again?
I'm not sure what your doing with the $register = mysql_fetch_array part, but to get the desired functionality you should use a select query to count the number of users using the username.
You're not using any secure hash format to store the password. I switched it to use password_hash().
Try something like this (I haven't tested the code yet though, so there might be errors):
<?php
//Put all POSTS in variables
$user = $_POST['user'];
$pass = password_hash($_POST['password'], PASSWORD_DEFAULT);
$email = $_POST['email'];
$email_check = $_POST['email_check'];
//Database config- probably should store in a separate file
$database_host = "";
$database_name = "";
$database_user = "";
$database_password = "";
$conn = new PDO("mysql:host=$database_host;dbname=$database_name",$database_user,$database_password);
//Find out if the username is taken.
$sql = "SELECT count(*) FROM `registration` WHERE user = :user";
$q = $conn->prepare($sql);
$q->execute(array(':user' => $user));
$number_of_rows = $q->fetchColumn();
//Clear $sql and $q so you can use them again
$sql = NULL;
$q = NULL;
if ($number_of_rows > 1) {
//Username already taken
echo "Username already taken";
}
else {
$sql = "INSERT INTO registration (user,password,email) VALUES (:user,:password,:email)";
$q = $conn->prepare($sql);
$q->execute(array(':user'=>$user, ':password'=>$password, ':email'=>$email));
echo "The account " . $user . " was successfully created";
}
?>
You really, really need to read about prepared statements. The method you are using is very old, incredibly insecure, and generally a bad-practice by today's standards.
Your code isn't even worth fixing for these reasons, it should be re-written using prepared statements.
I have successfully used Phpass to hash registered users passwords and store them in a database, now i am stuck on the login how to check the sumbitted username and password, checking the username exists in the database then checking the hashed password against the one given.
Any help much appreciated!!! Thankyou!
This is my code:
<?php
// Inialize session
session_start();
// Include database connection settings
include('config.inc');
require("PasswordHash.php");
$hasher = new PasswordHash(8, false);
$username = $_POST['username'];
$password = $_POST['password'];
// Passwords should never be longer than 72 characters to prevent DoS attacks
if (strlen($password) > 72) { die("Password must be 72 characters or less"); }
$query = "SELECT * FROM user WHERE username = '$username'";
$query = mysql_query($query);
$numrows = mysql_num_rows($query);
if ($numrows = 1) {
$res = mysql_query("SELECT password FROM user WHERE username = '$username'");
$row = mysql_fetch_array($res);
$hash = $row['password'];
$password = $_POST['password'];
if ($hasher->CheckPassword($password, $hash)) { //$hash is the hash retrieved from the DB
$what = 'Authentication succeeded';
} else {
$what = 'Authentication failed';
}
} else {
echo "No Such User";
include 'login.php';
exit();
}
echo "$what\n";
echo "<br />";
echo "$hash";
?>
THIS IS MY WORKING CODE FOR BENEFIT OF OTHERS:
<?php
// Inialize session
session_start();
// Include database connection settings
include('config.inc');
require("PasswordHash.php");
$hasher = new PasswordHash(8, false);
$username = $_POST['username'];
$password = $_POST['password'];
// Passwords should never be longer than 72 characters to prevent DoS attacks
if (strlen($password) > 72) { die("Password must be 72 characters or less"); }
$query = "SELECT * FROM user WHERE username = '$username'";
$query = mysql_query($query);
$numrows = mysql_num_rows($query);
if ($numrows = 1) {
$res = mysql_query("SELECT * FROM user WHERE username = '$username'");
$row = mysql_fetch_array($res);
$hash = $row['password'];
$password = $_POST['password'];
if ($hasher->CheckPassword($password, $hash)) { //$hash is the hash retrieved from the DB
$what = 'Authentication succeeded';
} else {
$what = 'Authentication failed';
}
} else {
echo "No Such User";
include 'login.php';
exit();
}
echo "$what\n";
echo "<br />";
echo "$hash";
?>
Here's how phpass works: When you save the user's password (when they create it) you hash it before saving, like so:
$hash_iterations = 30;
$portable_hashes = FALSE;
$hasher = new PasswordHash($hash_iterations, $portable_hashes);
$hash_value = $hasher->HashPassword($actual_password);
Then save $hash_value in the database as the user's password. When you go to validate the user, look up the user by username. If found, compare the actual password from the database (stored hash) with a hash of what the user entered:
// $stored_hash is the value you saved in the database for this user's password
// $user_input is the POST data from the user with the actual password
$valid_password = $hasher->CheckPassword($user_input, $stored_hash);
Make sure to initialize the PasswordHash class the same way each time, with the same values for $hash_iterations and $portable_hashes, or the comparison won't work correctly.