The following code should be straight forward and simple, the insert into the db on signup creates a hash, but later when I try to login with the same password the hash it is creating isn't matching up to what is in the database (I had print_r's throughout to verify). Can someone see if I'm just overlooking something dumb?
session_start();
require_once("login.php");
$error = "";
$email = "";
$password = "";
if (isset($_GET['logout'])) {
unset($_SESSION['id']);
setcookie('id', '', time() - 60*60);
$_COOKIE['id'] = "";
} else {
if (isset($_SESSION['id']) or isset($_COOKIE['id'])) {
header("Location: loggedinpage.php");
}
}
if (isset($_POST["submit"])) {
$link = mysqli_connect($hn, $un,$pw,$db);
if($link->connect_error) die("Fatal Errror.");
if (!$_POST["email"]) {
$error .="An email address is required<br>";
}
if (!$_POST["password"]) {
$error .="A password address is required<br>";
}
if ($error != "") {
$error= "<p>There were error(s) in your form:</p>".$error;
} else {
if ($_POST['signup'] == 1) {
$email = mysqli_real_escape_string($link, $_POST['email']);
$password = mysqli_real_escape_string($link,$_POST['password']);
$query = "SELECT id FROM `users` WHERE email = '".$email."' LIMIT 1";
$result=$link->query($query);
if (mysqli_num_rows($result) > 0) {
$error = "That email address is taken.";
} else {
$hashedPassword = password_hash($password, PASSWORD_DEFAULT);
$query = "INSERT INTO `users`(`email`,`password`) VALUES ('".$email."', '".$hashedPassword."')";
if (!mysqli_query($link,$query)) {
$error = "<p>Could not sign you up, please try again later</p>";
} else {
$_SESSION['id'] = mysqli_insert_id($link);
if(isset($_POST['stayLoggedIn']) and $_POST['stayLoggedIn'] == 1) {
setcookie('id', mysqli_insert_id($link), time()+60*60*24);
}
header("Location: loggedinpage.php");
}
}
} else {
$email = mysqli_real_escape_string($link, $_POST['email']);
$password = mysqli_real_escape_string($link, $_POST['password']);
$hashedPassword = password_hash($password,PASSWORD_DEFAULT);
$query = "SELECT * FROM users WHERE email = '".$email."' LIMIT 1";
$result = $link->query($query);
if ($result->num_rows > 0) {
$row = $result->fetch_array(MYSQLI_ASSOC);
if ($email == $row['email'] and password_verify($password,$row['password'])) {
if (isset($_POST['stayLoggedIn']) and $_POST['stayLoggedIn'] == 1) {
setcookie('id', $row['id'], time()+60*60*24);
header("Location: loggedinpage.php");
}
} else {
$error = "Incorrect Username/Password combination";
}
}
}
}
}
Although it's tucked away at the end of a paragraph, PHP documentation does say that "it is recommended to store the result in a database column that can expand beyond 60 characters (255 characters would be a good choice)."
The current default algorithm, bcrypt, generates hashes that are 60 characters long. If your database column cannot hold at least this many characters, your hashes will be truncated and verification will fail.
You've got a few other problems as well:
You're modifying the password before generating the hash (with mysqli_real_escape_string())
You're not using prepared statements
You appear to be relying on cookies for authentication. Cookies are user-generated data, they are not to be trusted! This is why PHP provides session support, because the data is stored on the server.
You should not be checking for an existing email address using a query, instead you should have a unique index set on the email column in the database.
try
if(password_verify($password, (string)$row->password)){
//Your Code
}
because of password_verify function return Boolean only true or false
And
$hashedPassword = password_hash($password,PASSWORD_DEFAULT);
Only add once when you Insert to Sql (new user)
Related
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(); }
?>
I am doing a password reset page for my website and when a user puts a new password on the <form method="post" action="passVerif.php"> it goes to the PHP with this code:
Until now I cannot make the php compare the two new entered passwords to verify if they are equal or not, it simply jumps over that part.
P.S. don't mind the $senha = md5($password) it is like this for easy troubleshoot on localhost (MAMP).
<?php
session_start();
include("connectivity.php");
$user_id = $_SESSION['ResetUtilizadorID'];
$password1 = $_POST['password1'];
$password2 = $_POST['password2'];
$sql = mysqli_query($conn, "SELECT FROM usuarios WHERE id =".$user_id."");
$password = $password1;
$senha = md5($password);
$adminID = $_SESSION['usuarioNiveisAcessoId'];
if (strcmp($user_id,$adminID) == 0) {
$_SESSION['avisoReset'] = "not possible to change admin password.";
header('Location: ../login/reset_password.php');
} else {
while ($row = mysqli_fetch_array($query)) {
if ($senha == $row['senha']){
$_SESSION['avisoReset'] = "password taken";
header('Location: ../login/reset_password.php');
}
}
if ($password1 == $password2){
mysqli_query($conn, "UPDATE usuarios SET senha = '".$senha."' WHERE id='".$user_id."'");
$sql = 'SELECT * FROM usuarios';
$query = mysqli_query($conn, $sql);
if (!$query) {
die ('SQL Error: ' . mysqli_error($conn));
}
$_SESSION['avisoReset'] = "new passoword set";
//header('Location: ../login/reset_password.php');
} else {
$_SESSION['avisoReset'] = "Passwords not equal!";
header('Location: ../login/reset_password.php');
}
}
?>
Why are you using strpos? strpos finds the position of the first occurrence of a substring in a string. So the password could be a subset of another string (the stored password) and still evaluate to true for your use case.
if (strpos($user_id,$adminID) == true)
You should instead use strcmp (Binary safe string comparison):
if (strcmp($user_id,$adminID) == 0)
I solved the problem by adding a username and then comparing the user input data to the DB. So the problem of multiple users by any chance use the same password it is all good.
This question already has answers here:
How to check if a row exists in MySQL? (i.e. check if username or email exists in MySQL)
(4 answers)
Closed 5 years ago.
I would like to check for duplicates in a MySQL database when registering an user.
If the user exists display an error to that effect, else sign up.
I know there's a few questions like this but I found it hard to paste any of them into my code.
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
//two passwords are the same
if($_POST['password'] == $_POST['confirmedpassword']) {
$username = $mysqli->real_escape_string($_POST['username']);
$password = md5($_POST['password']);
$_SESSION['username'] = $username;
$_SESSION['password'] = $password;
$sql = "INSERT INTO members(username, password)"
. "VALUES ('$username','$password')";
//if query is successful redirect to login.php
if ($mysqli->query($sql) === true)
$_SESSION['message'] = 'Success';
header("location: login.php");
} else {
$_SESSION['message'] = "User couldnt be added";
}
} else {
$_SESSION['message'] = "Passwords dont match";
}
}
I added some salt to your md5 password to make it seem more secure, but actually this solution is not secure either. To encrypt passwords in PHP it is advisable to use the password_hash() function like this:
$pass = password_hash($password, PASSWORD_BCRYPT);
password_hash() creates a new password hash using a strong one-way hashing algorithm.
and later test it with password_verify():
password_verify ( $passToTest , $knownPasswordHash );
more the functions here: http://php.net/password-hash, http://php.net/password-verify.
Also, since you are using MySQLi consider using prepared statements, or at least properly filter your input data before applying it to the database.
More on prepared statements: http://php.net/prepared-statements.
I added a select statement to check if the user already exists in the table prior to adding the user to the database.
When using header() to change page location put exit() or die() in the next line of code if you want to exit immediately and don't want other code to execute.
Here is your code with the addition of the select statement:
<?php
if ($_SERVER['REQUEST_METHOD'] == 'POST')
{
//two passwords are the same
if($_POST['password'] == $_POST['confirmedpassword'])
{
$username = $mysqli->real_escape_string($_POST['username']);
// You might consider using salt when storing passwords like this
$salt = 'aNiceDay';
$password = md5(md5($_POST['password'].$salt).$salt);
$_SESSION['username'] = $username;
$_SESSION['password'] = $password;
$sql = "SELECT `username` FROM members WHERE `username` = '".$username."'";
$result = $mysqli->query($sql);
if(mysqli_num_rows($result) > 0)
{
echo 'User exists.';
// Do something.
}
else
{
$sql = "INSERT INTO members(username, password) VALUES ('".$username."','".$password."')";
if($mysqli->query($sql) === true)
{
$_SESSION['message'] = 'Success';
header("location: login.php");
// Important to put exit() after header so other code
// doesn't get executed.
exit();
}
else
{
$_SESSION['message'] = "User couldn't be added";
echo "User couldn't be added.";
}
}
}
else
{
$_SESSION['message'] = "Passwords dont match";
}
}
?>
So you can check that the user exists or not.
if ($_SERVER['REQUEST_METHOD'] == 'POST'){
//two passwords are the same
if($_POST['password'] == $_POST['confirmedpassword']) {
$username = $mysqli->real_escape_string($_POST['username']);
$password = md5($_POST['password']);
$_SESSION['username'] = $username;
$_SESSION['password'] = $password;
//Check user
$CheckUserIsExist = mysqli->query("SELECT uid FROM members WHERE username='$username'");
if(mysqli_num_rows($CheckUserIsExist)==0 ){
$sql = "INSERT INTO members(username, password)"
. "VALUES ('$username','$password')";
//if query is successful redirect to login.php
if($mysqli->query($sql) === true)
$_SESSION['message'] = 'Success';
header("location: login.php");
}
} else{
echo 'This username is already in use. Please use different username';
}
else{
$_SESSION['message'] = "User couldn't be added";
}
}
else{
$_SESSION['message'] = "Passwords don't match";
}
I am working on php and mysql code on making access to different pages based on the role of the user, through one Login Page.
Its working good for 'admin' page ..
but not able to login with 'normal type'
Little Help is really appreciated, Thank You
Here is my Code
<?php
session_start();
include 'dbcon.php';
if($_SERVER["REQUEST_METHOD"] == "POST") {
$username = $_POST['username'];
$password = $_POST['password'];
$query = "SELECT * FROM wp_users WHERE user_login = '$username' AND user_pass = '$password'";
$result = mysqli_query($con,$query) ;
$row = mysqli_fetch_assoc($result);
$count=mysqli_num_rows($result) ;
if ($count == 1) {
if($row['user_type'] == 'admin')
{
header('Location: user_registration.php');
$_SESSION['ID'] = $row['ID'];
$_SESSION['user_login'] = $row['user_login'];
$_SESSION['password'] = $row['user_pass'];
}
elseif($row['user_type'] = 'normal')
{
header('Location: index.php');
}
else
{
echo "WRONG USERNAME OR PASSWORD";
}
}
}
?>
Move your session code after if condition and then redirect. Also is there any specific reason to store password in session. == missing
Use proper filters for inputs.
if ($count == 1) {
if(!empty($row['user_type'])) {
$_SESSION['ID'] = $row['ID'];
$_SESSION['user_login'] = $row['user_login'];
//$_SESSION['password'] = $row['user_pass'];
}
if($row['user_type'] == 'admin')
{
header('Location: user_registration.php');
}
elseif($row['user_type'] == 'normal')
{
header('Location: index.php');
}
else
{
echo "WRONG USERNAME OR PASSWORD";
}
}
The logic test for the normal user was using a single = sign which sets a value rather than tests for equality - it needs to be ==
Also, I think the WRONG USERNAME OR PASSWORD wa at the wrong level - it needs to be the else to the record count
<?php
session_start();
include 'dbcon.php';
if($_SERVER["REQUEST_METHOD"] == "POST") {
$username = $_POST['username'];
$password = $_POST['password'];
$query = "SELECT * FROM wp_users WHERE user_login = '$username' AND user_pass = '$password'";
$result = mysqli_query($con,$query);
$row = mysqli_fetch_assoc($result);
$count=mysqli_num_rows($result);
if ($count == 1) {
if($row['user_type'] == 'admin') {
header('Location: user_registration.php');
$_SESSION['ID'] = $row['ID'];
$_SESSION['user_login'] = $row['user_login'];
$_SESSION['password'] = $row['user_pass'];
/* require `==` here */
} elseif( $row['user_type'] == 'normal' ) {
header('Location: index.php');
} else {
die('unknown/unhandled user level');
}
/* changed location of this by one level */
} else {
echo "WRONG USERNAME OR PASSWORD";
}
}
?>
This is function for login.
It presumes password come from user with sha512 encryption (see js libs like https://github.com/emn178/js-sha512) - it's good for non-encrypted connections.
It uses salt, and have some protection from brute force, CSRF, XSS and SQL-injection.
static public function db_login($email, $p)
{
if ($stmt = Site::$db->prepare(
"SELECT id, password, salt, name
FROM user
JOIN contact ON contact_id = id
WHERE email = ?
LIMIT 1")
) {
$stmt->bind_param('s', $email);
$stmt->execute();
$stmt->store_result();
$stmt->bind_result($user_id, $db_password, $salt, $name);
$stmt->fetch();
// hash the password with the unique salt
$p = hash('sha512', $p . $salt);
if ($stmt->num_rows == 1) {
// If the user exists we check if the account is locked
// from too many login attempts
if (self::checkBrute($user_id) == true) {
// Account is locked
$res['code'] = 0;
$res['reason'] = 'trylimit';
$res['message'] = 'You try too many times. Come back on 30 minutes';
return $res;
} else {
// Check if the password in the database matches
// the password the user submitted.
if ($db_password == $p) {
// Password is correct!
// Get the user-agent string of the user.
// CSRF
$user_browser = filter_input(INPUT_SERVER, 'HTTP_USER_AGENT', FILTER_SANITIZE_SPECIAL_CHARS);
// XSS protection as we might print this value
$user_id = preg_replace("/[^0-9]+/", "", $user_id);
Login::sec_session_start();
$_SESSION['user_id'] = $user_id;
$_SESSION['email'] = htmlspecialchars($email);
$_SESSION['name'] = htmlspecialchars($name);
$_SESSION['token'] = md5(uniqid(rand(), TRUE));
$_SESSION['login_string'] = hash('sha512', $p . $user_browser);
session_write_close();
// Login successful
$res['isLogined'] = 1;
$res['code'] = 1;
$res['name'] = $name;
$res['id'] = $user_id;
return $res;
} else {
// Password is not correct
// We record this attempt in the database
$now = time();
Site::$db->query("INSERT INTO login_attempts(user_id, time) VALUES ('$user_id', '$now')");
$res['code'] = 0;
$res['reason'] = 'pass';
$res['message'] = 'Wrong password';
return $res;
}
}
} else {
// No user exists.
$res['code'] = 0;
$res['reason'] = 'user';
$res['message'] = 'We have no such email';
return $res;
}
}
$res['code'] = 0;
$res['reason'] = 'SQL-error';
return $res;
}
I'm trying to make a login system (already have registration system complete) with password_hash() and password_verify() but it isn't working for me. I've been trying to find an answer this whole morning and yet can't seem to make it work, I've watched codecourse tutorials, read blog posts and nothing. The tutorial I've been following the most is this one.
<!-- login -->
<?php
if($_SERVER['REQUEST_METHOD'] == "POST") {
$errors = array();
error_reporting(E_ALL);
ini_set('display_errors', 1);
//Basic validation
if(empty($_POST['username'])){
$errors[] = "Please enter your username";
}else{
$username = $mysqli->real_escape_string($_POST['username']);
}
if(empty($_POST['password'])){
$errors[] = "Please enter your password";
}else{
$password = trim($_POST['password']);
}
if (empty($errors)) {
$sql = "SELECT * FROM users WHERE username = '$username'";
$result = $mysqli->query($sql);
if ($result->num_rows === 1) {
$row = $result->fetch_array(MYSQLI_ASSOC);
if(password_verify($password, $row['password'])) {
echo 'test';
$_SESSION['user']['user_id'] = $row['user'];
header("Location: google.com");
exit();
}else{
$errors[] = "The username or password do not match";
}
}else{
$errors[] = "The username or password do not match";
}
}
}
?>
<!-- register -->
<?php
if($_SERVER['REQUEST_METHOD'] == "POST") {
$username = mysqli_real_escape_string($conn, $_POST['username']);
$password = $_POST['password'];
$hashed_password = password_hash($password, PASSWORD_DEFAULT);
$confirm_password = mysqli_real_escape_string($conn, $password);
$ip = $_SERVER['REMOTE_ADDR'];
if(empty($username) || empty($password) || empty($confirm_password)) {
$error = "Fill in the missing fields";
} else {
$sql = "INSERT INTO users VALUES('', '$username', '$hashed_password', '$ip', 'User')";
if($conn->query($sql) === TRUE) {
$error = "Your account has been created.";
} else {
$error = "Your account has not been created, please try again later.";
}
}
}
?>
The end result product is supposed to login in successfully and redirect, I'm using PHP 5.6 and running on localhost XAMPP.
You'll never get a match because you're using
$password =mysqli_real_escape_string($conn, $_POST['password']);
to store the password and then not using it on verification. Instead you use
$password = trim($_POST['password']);
Make sure you don't escape passwords or use any other cleansing mechanism on them before hashing. Doing so changes the password and causes unnecessary additional coding. The password_hash() function can generate some very lengthy text (the current default is 60 characters), so make sure the field in your database is large enough to accommodate the hash. Setting the field larger now will allow for the length needed. The PHP team is adding more algorithms to the method which means the hash can and will grow.