PHP crypt validation with PDO prepared statement Error - php

and sorry for the [duplicate]. i spent a day, not able to find a solution. I am having a problem with crypt (validation), here is my code:
function generateHash($password, $round=10){
$salt=substr(base64_encode(openssl_random_pseudo_bytes(17)),0,22);
$salt=str_replace("+",".",$salt);
$param='$'.implode('$',array(
"2y",
str_pad($round,2,"0",STR_PAD_LEFT),
$salt
)
);
return crypt($password,$param);
}
//NOW I INSERT HASH TO DB
$input = "abc";
$hashed = generateHash($input);
$createAccount=$db->prepare("INSERT INTO account ....
':secret' => $hashed;
.....)); // Until here, no problem, $hashed can be inserted correctely into my db (password, Varchar (64)
Now after registration, user likes to login, here is the problem. First, i'm checking, to see, if i did well the function
$input = "abc";
$forCheck = "abc";
$hashedHash = generateHash($input);
if (crypt($forCheck, $hashedHash) == $hashedHash) {
echo "MATCH";
}else {
echo "NOT MATCH";
}
// OUTPUT: "MATCH"
The problem is here:
$check=$db->prepare("SELECT id, password FROM account WHERE email = :email ");
$check->execute(array(
':email' => $user
)
);
if ($check->rowCount() <= 0) {
echo "You are not registered";
}else {
$sRow=$check->fetchAll(PDO::FETCH_ASSOC);
foreach ($sRow as $row) {
$hashedHash = generateHash($row['password']);
if (crypt($input, $hashedHash) == $hashedHash) {
echo "Passwords Matched";
}else {
echo "Passwords did not match";
}
}
}
// OUTPUT: "Passwords did not match"
Any help please ?

The problem is here...
$hashedHash = generateHash($row['password']);
You aren't storing a plain text password so why would you pass the hash through generateHash again? Should simply be
if (crypt($input, $row['password']) == $row['password'])
I'd also take this opportunity to clean up your query logic. For one thing, PDOStatement::rowCount should not be relied upon.
$check = $db->prepare('SELECT id, password FROM account WHERE email = :email LIMIT 1');
$check->execute([':email' => $user]);
if ($row = $check->fetch(PDO::FETCH_ASSOC)) {
if (crypt($input, $row['password']) == $row['password']) {
echo 'Passwords Matched';
} else {
echo 'Password did not match';
}
} else {
echo 'You are not registered';
}

Related

How to use the encrypt password for login php [duplicate]

This question already has answers here:
How to use PHP's password_hash to hash and verify passwords
(5 answers)
Closed 1 year ago.
At first I am using md5 for hashing but then I learn that password_hash is more secured, but when I tried to use it in my website it wont work. I've tried putting the code password_verify everywhere.
When I'm trying to login it just giving me an error of password/ email combination is wrong even if it is correct. I also get the error for the password verify but when I put the correct credentials it's still giving me the error message
This is my login code
<?php
function login(){
global $db, $email, $errors;
// grab form values
$email = e($_POST['email']);
$password = e($_POST['password']);
// make sure form is filled properly
if (empty($email)) {
array_push($errors, "Email is required");
}else {
$email = hsc($_POST["email"]);
}
if (empty($password)) {
array_push($errors, "Password is required");
}else{
$password = hsc($_POST["password"]);
}
// attempt login if no errors on form
if (count($errors) == 0) {
$query = "SELECT * FROM accounts WHERE email='$email' AND password='$password' LIMIT 1";
$results = mysqli_query($db, $query);
if (password_verify($password, $_POST["password"])) {
array_push($errors, "Wrong password");
}
if (mysqli_num_rows($results) == 1) { // user found
// check if user is admin or user
$logged_in_user = mysqli_fetch_assoc($results);
if ($logged_in_user['user_type'] == 'admin') {
$_SESSION['user'] = $logged_in_user;
$_SESSION['success'] = "You are now logged in";
header('location: admin/admin.php');
exit(0);
}else{
$_SESSION['user'] = $logged_in_user;
$_SESSION['success'] = "You are now logged in";
header('location: index.php');
exit(0);
}
}else {
array_push($errors, "Wrong username/password combination");
}
}
}
This is my register code (There are all in the same file functions.inc.php)
function register(){
// call these variables with the global keyword to make them available in function
global $db, $errors, $username, $email;
// receive all input values from the form. Call the e() function
// defined below to escape form values
$username = e($_POST['username']);
$email = e($_POST['email']);
$password_1 = e($_POST['password']);
$password_2 = e($_POST['re-password']);
//check email if already exist on database
$check = "SELECT * FROM accounts WHERE email='$email'";
$res_e = mysqli_query($db, $check);
// form validation: ensure that the form is correctly filled
if (empty($username)) {
array_push($errors, "Name is required");
}elseif (!preg_match("/^[a-zA-Z]+( [a-zA-Z]+)*$/",$username)) {
array_push($errors, "Only letters and one space only");
}else{
$username = hsc($_POST["username"]);
}
if (empty($email)) {
array_push($errors, "Email is required");
}elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
array_push($errors, "The email is invalid");
}elseif (mysqli_num_rows($res_e) > 0) {
array_push($errors, "The email already taken");
}else{
$email = hsc($_POST["email"]);
}
if (empty($password_1)) {
array_push($errors, "Password is required");
}elseif ($password_1 != $password_2) {
array_push($errors, "The two passwords do not match");
}else{
$password_1 = hsc($_POST["password_1"]);
}
// register user if there are no errors in the form
if (count($errors) == 0) {
$hashpassword = password_hash($password_1, PASSWORD_DEFAULT);;//encrypt the password before
saving in the database
if (isset($_POST['user_type'])) {
$user_type = e($_POST['user_type']);
$query = "INSERT INTO accounts (username, email, user_type, password)
VALUES('$username', '$email', '$user_type', '$hashpassword')";
mysqli_query($db, $query);
$_SESSION['add'] = "Added successfully";
header('location: users.php');
exit(0);
}else{
$query = "INSERT INTO accounts (username, email, user_type, password)
VALUES('$username', '$email', 'user', '$hashpassword')";
mysqli_query($db, $query);
// get id of the created user
$logged_in_user_id = mysqli_insert_id($db);
$_SESSION['user'] = getUserById($logged_in_user_id); // put logged in user in session
$_SESSION['add'] = "You are now logged in and thank you!";
header('location: index.php');
exit(0);
}
}
}
I don't know if this is also the reason that the login is not working but it is better that I put it in. This is the code for function hsc() and e()
// escape string
function e($val){
global $db;
return mysqli_real_escape_string($db, trim($val));
}
// htmlspecialchars the inputs data
function hsc($val) {
$val = htmlspecialchars($val);
return $val;
}
Here is the data base photo
(By far the simplest method...)
Try this example. It uses Argon2, which is by far the safest encryption method (AFAIK)
Note that it randomly generates a different string when run, so using password_verify is mandatory unlike using sha-256 to look up the password in the database
<?php
$pwd = password_hash("my password goes here", PASSWORD_ARGON2I);
// Use $_POST instead
echo $pwd;
?>
And to verify your password:
if(password_verify($_POST['password'], $row["password"])) {
// Your code here...
}
Also, use PDP PDO, it's much safer against SQL injection attacks
<?php
$db = new PDO('mysql:host='.$servername.';dbname='.$dbname.';charset=utf8mb4', $username, $password);
try {
$query = "SELECT * from `login` WHERE `username`=:username OR `email` =:usernamea";
$stmt = $db->prepare($query);
$stmt->bindParam('username', $username, PDO::PARAM_STR);
$stmt->bindParam('usernamea', $username, PDO::PARAM_STR);
$stmt->execute();
$count = $stmt->rowCount();
$row = $stmt->fetch(PDO::FETCH_ASSOC);
if($count == 1 && !empty($row)) {
$auth_email = $row['email'];
$auth_pwd = $row['password'];
if(password_verify($_POST['password'], $auth_pwd)) {
$validuser = $row['username'];
$_SESSION['valid'] = $validuser;
$_SESSION['name'] = htmlspecialchars($row['name']);
}
else {
echo 'Invalid';
}
}
else {
echo 'Invalid';
}
}
catch (PDOException $e) { echo "Error : ".$e->getMessage(); }
?>

Add password hash in pdo login

I cannot manage to add a password hash in my sign up code. I am new to PDO and I tried different things but cannot manage to make a working registration with password hash!
Can someone help me? Here my code:
<?php
include('header.php');
// Check if logged in
if($user->is_loggedin()!="")
{
$user->redirect('home.php');
}
$error='';
if(isset($_POST['btn-signup']))
{
// trim empty spaces on inserted data
$uname = trim($_POST['name']);
$umail = trim($_POST['email']);
$upass = trim($_POST['password']);
$repeat_password = trim($_POST['repeat_password']);
// validate username
if($uname=="") {
$error.= "provide username ! <br>";
}
// validate e-mail
else if($umail=="") {
$error.= "provide email id ! <br>";
}
else if(!filter_var($umail, FILTER_VALIDATE_EMAIL)) {
$error.= 'Please enter a valid email address ! <br>';
}
// validate password
else if($upass=="") {
$error.= "provide password ! <br>";
}
else if(strlen($upass) < 6){
$error.= "Password must be atleast 6 characters <br>";
}
else if( $upass!=$repeat_password){
$error.= "Password Does Not Match <br>";
}
else
{
// check if email is already taken
try
{
// prepare statement
$stmt = $DB_con->prepare("SELECT email FROM users WHERE email=:umail");
$stmt->execute(array(':umail'=>$umail));
$row=$stmt->fetch(PDO::FETCH_ASSOC);
if($row['email']==$umail) {
$error.= "sorry email id already taken ! <br>";
}
// if everything is validated save data
else
{
if($user->register($uname,$umail,$upass))
{
$_SESSION['success']='You have been Registered Successfully';
$user->redirect('login.php');
}
}
}
// set the error mode
catch(PDOException $e)
{
echo $e->getMessage();
}
}
}
And here the class "user"
<?php
class User
{
private $db;
function __construct($DB_con)
{
$this->db = $DB_con;
}
// get user by passed in data
public function register($uname,$umail,$upass)
{
try
{
// $new_password = password_hash($upass, PASSWORD_DEFAULT); // Creates a password hash;
$new_password = $upass;
// prepared statement
$stmt = $this->db->prepare("INSERT INTO users(name,email,password,user_type)
VALUES(:uname, :umail, :upass,'user')");
// bind param with values
$stmt->bindparam(":uname", $uname);
$stmt->bindparam(":umail", $umail);
$stmt->bindparam(":upass", $new_password);
$stmt->execute();
return $stmt;
}
// set the error mode
catch(PDOException $e)
{
echo $e->getMessage();
}
}
public function login($umail,$upass)
{
try
{
// prepare statement
$stmt = $this->db->prepare("SELECT * FROM users WHERE email=:umail LIMIT 1");
$stmt->execute(array(':umail'=>$umail));
$userRow=$stmt->fetch(PDO::FETCH_ASSOC);
if($stmt->rowCount() > 0)
{
if($upass==$userRow['password'])
{
$_SESSION['user_id'] = $userRow['id'];
$_SESSION['name'] = $userRow['name'];
$_SESSION['role'] = $userRow['user_type'];
return true;
}
else
{
return false;
}
}
}
// set the error mode
catch(PDOException $e)
{
echo $e->getMessage();
}
}
public function is_loggedin()
{
if(isset($_SESSION['user_id']))
{
return true;
}
}
public function redirect($url)
{
header("Location: $url");
}
public function logout()
{
session_destroy();
unset($_SESSION['user_id']);
return true;
}
}
?>
In the commented line in the class script you can see a try I made, it hashed the password but then the pw wouldn't be saved in my sql database.
Sorry if the question is stupid but I am learning :)
I want to point out few things first:
Do not use trim to users password. Unless if you want to restrict your users from entering spaces to their passwords.
Use === when doing comparison. It is better because it checks datatype at the same time. For example if you have "2" and 2 and you use == operator it equals. It is good practice to check datatype because it prevents alot error from happening.
As what comes to problem that you wanted to get answer
You don't use password_hash function at any point. You only assign raw password to variable and assign this variable to bind_param function.
$new_password = $upass;
Should be instead
$new_password = password_hash($upass, PASSWORD_DEFAULT);
However i do not recommend using PASSWORD_DEFAULT as you could get more secure hash by using PASSWORD_ARGON2I. You can check more information about password_hash from PHP manual.
And to help you out even more: when you want to verify that user enters correct password at login you need to use password_verify(). It compares hash to password that user entered and if it is correct this function will return true.
Example:
$login_status = password_verify($_POST['password'], $user_password_from_database);
if($login_status === true) {//set session etc...}
You can read more about password_verify here

Why PHP authentication works incorrect?

I am newbie in PHP.
I have simple authentication script. It works incorrect: user "test" (100% existing in table in DB) can not pass auth (error text - "User is not found!").
Use PHP7, MySQL, connection method is PDO.
Need some help please.
$data = $_POST;
// check if button is pressed
if (isset($data['enter-auth'])) {
// check fileds
$errors = array();
if (trim($data['login_auth']) == '' ) {
$errors[] = 'Enter login';
}
if (($data['password_auth']) == '' ) {
$errors[] = 'Enter password';
}
// If all fields are filled, save user's data in vars
$login = $data['login_auth'];
$password = password_hash($data['password_auth'], PASSWORD_DEFAULT);
// ... and look in table
try {
if (empty($errors)) {
// Check if login and password exists in table
$stmt = $pdo->prepare("SELECT count(*) FROM users WHERE login=? AND password=?");
$stmt->execute([$login, $password]);
$count = $stmt->fetchColumn();
// If login and pwd found in table counter will be > 0, so ...
if ($count > 0) {
// ... then we can check if password is correct
if (password_verify($data['password_auth'], $password)) {
// if entered and stored passwords match, user is welcome
$_SESSION['auth_name'] = $data['login_auth'];
echo '<div style="color: green;">Welcome, '.$_SESSION['auth_name'].';
echo 'Exit';
header('Location: /a/index.php');
} else {
$errors[] = 'Password is incorrect';
echo '<p id="message">Wrong password!</p>';
}
} else {
$errors[] = 'User not found';
echo '<p id="message">User is not found!</p>';
}
} else {
echo '<div style="color: red;">'.array_shift($errors).'</div>';
}
} catch(PDOException $e) {
echo $e->getMessage();
}
// close condition check if button is pressed
}
Notes:
I tryed debugging this script using var_dump.
If I use fetchAll() when searching in table, any entered ldin is accepted (even if there is no such user).
Used try/catch construction with debug aim, I've heard that in production it is deprecated because of security reason.
Found mistakes, rewrote the code according to https://phpdelusions.net/pdo_examples/password_hash
So, correct fragment is:
try {
if (empty($errors)) {
$stmt = $pdo->prepare("SELECT login, password FROM users WHERE login=?");
$stmt->execute([$login]);
$user = $stmt->fetch();
if ($user && password_verify($data['password_auth'], $user['password'])) {
$_SESSION['auth_name'] = $data['login_auth'];
echo '<div style="color: green;">Welcome, '.$_SESSION['auth_name'].';
echo 'Exit';
header('Location: /a/index.php');
} else {
$errors[] = 'Login or password error';
echo '<p id="message-auth">Login or password is incorrect!</p>';
}
} else {
echo '<div style="color: red;">'.array_shift($errors).'</div>';
}
} catch(PDOException $e) {
echo $e->getMessage();
}

PHP returns multiple strings

I'm trying to build a login page for my forums using Apache and MySQL XAMPP Databases, But it returns the echo string multiple times, I know it goes through all of the rows in the database checking if it's true or not it returns it as "Invalid Username or Password!" until it Finds the correct login information then returns "Welcome" Might be.
while($rows = mysql_fetch_row($result)) {
//echo $rows;
if($name==$rows[1]) {
if($pass==$rows[2]) {
echo "Welcome!";
}
}
else if ($name!==$rows[1]) {
echo "Invalid Username or Password!";
if($pass!==$rows[2]) {
echo "Invalid Username or Password!";
}
}
$row = $row + 1;
}
Here is my Output:
Invalid Username or Password!Invalid Username or Password!Invalid
Username or Password!Invalid Username or Password!Welcome!
How is it done so it returns just the one that is incorrect and correct strings?.
I'm going about this from a different perspective. First of all the mysql_* extension is deprecated in as of PHP 5.5.0 and it's use is discouraged.
The next thing is I think you're going the wrong way about this. Why loop through the entire table for credentials when you can just check if there is a record with that username and that password? This is highly inefficient.
$stmt = $mysqli->prepare("SELECT * FROM users WHERE username = ? && password = ?");
$stmt->bind_param("ss", $name, $pass);
$stmt->execute();
$stmt->store_result();
$stmt->close();
// we found a record so the username and password match
if ($stmt->num_rows > 0) {
echo 'Welcome!';
// no records so either the username or password doesn't match
} else {
echo 'Invalid Username or Password!';
}
Keep your code outside loop for return one row
$rows = mysql_fetch_row($result);
//echo $rows;
if($name==$rows[1]) {
if($pass==$rows[2]) {
echo "Welcome!";
}
}
else if ($name!==$rows[1]) {
echo "Invalid Username or Password!";
if($pass!==$rows[2]) {
echo "Invalid Username or Password!";
}
}
use simple code
$sql=mysql_query("select * from `admin_details` where admin_email='$email' and admin_pass='$pass'");
if (mysql_num_rows($sql) > 0) {
echo "Welcome!";
} else {
echo "Invalid Username or Password!";
}

ban and user activation system but I have some problems on the login script

I'm new to php. I have a login system, and now I'm trying to implement a ban and user activation system but I have some problems on the login script. Here is the code from my script:
<?php
$query = "SELECT id, username, password, salt, email, firstname, lastname, active, banned FROM users WHERE username = :username ";
$query_params = array(
':username' => $_POST['username']
);
try
{
$stmt = $db->prepare($query);
$result = $stmt->execute($query_params);
}
catch(PDOException $ex)
{
die("Failed to run query: " . $ex->getMessage());
}
$row = $stmt->fetch();
$login_ok = false;
$login_match = false;
$login_active = false;
$login_banned = false;
if($row)
{
$check_password = hash('sha256', $_POST['password'] . $row['salt']);
if($check_password === $row['password'])
{
$login_match = true;
}
if($row['active'] == 1) {
$login_active = true;
}
if($row['banned'] == 1) {
$login_banned = true;
}
if($login_match && $login_active && !$login_banned) {
$login_ok = true;
}
}
if($login_ok)
{
unset($row['salt']);
unset($row['password']);
$_SESSION['user'] = $row;
header("Location: index.php");
die("Redirecting...");
}
else
{
if(!$login_match) { echo "Wrong username/pasword.";}
if(!$login_active) { echo "Account not activated, check your email";}
if($login_banned) { echo "Your account is banned";}
}
?>
In my Database I have 2 columns active and banned, where 0 means that account is activated and not banned, and 1 if account is not activate or is banned.
How can I display different messages to the user? If a user will enter a wrong username or password, he will get all three messages from the final else {}. I want to display messages to the user like this:
If username or password is wrong, display only Wrong username/pasword. and ignore $login_active $login_banned.
If username/password is ok, but account not activated, Account not activated, check your email. and ignore the $login_banned switch.
If username/password is ok, but account is banned display Your account is banned and ignore the $login_active switch.
I'm sorry if I wrote too much, I hope I explained right.
Change this:
if(!$login_match) { echo "Wrong username/pasword.";}
if(!$login_active) { echo "Account not activated, check your email";}
if($login_banned) { echo "Your account is banned";}
To this:
<?php
if ($login_banned == true) {
echo "Your account is banned";
} else if ($login_match != true) {
echo "Wrong username/password.";
} else if ($login_active != true) {
echo "Account not activated, check your email";
}
?>
I hope it does what you want.
Below are options you could still use:
//PICK OPTIONS DEPENDING ON YOUR PREFERENCE AND MESSAGE PRIORITIES
//option 1
if ($login_match != true) {
echo "Wrong username/pasword.";
} else if ($login_banned != true) {
echo "Your account is banned";
} else if ($login_active != true) {
echo "Account not activated, check your email";
}
//option 2
if ($login_match != true) {
echo "Wrong username/pasword.";
} else if ($login_active != true) {
echo "Account not activated, check your email";
} else if ($login_banned != true) {
echo "Your account is banned";
}
//option 3
if ($login_banned == true) {
echo "Your account is banned";
} else if ($login_match != true) {
echo "Wrong username/password.";
} else if ($login_active != true) {
echo "Account not activated, check your email";
}

Categories