I'm trying to make an authentication form with PHP and MySQL but it doesn't work and I'm wondering why.
Is there anybody who can help me ? I did a password hash in a precedent file, but they are not linked. This one is independant .
Thank you !
<?php
session_start();
function connect_db($host, $port, $db, $username, $password)
{
$pdo = new PDO("mysql:host=$host; port=$port; dbname=$db", $username, $password);
return $pdo;
}
if (isset($_POST["email"]) && isset($_POST["password"]) && !empty($_POST["email"]) && !empty($_POST["password"]))
{
$error_pass= "";
$email = $_POST["email"];
$password = $_POST["password"];
try
{
$pdo = connect_db("localhost", 3306, "*******", "******", "*******");
$sql = $pdo-> prepare("SELECT * FROM users WHERE email = :email AND password = :password");
$sql->bindParam(':email', $email);
$sql->bindParam(':password', $password);
$sql->execute();
$req = $sql->fetch();
echo $req["password"] . "SALUT \n";
var_dump($req["password"]);
if (password_verify($password, $req['password']) == 0) {
session_unset();
$error_pass = "Incorrect email/password";
}
else {
$_SESSION["name"] = $req["name"];
header("Location: index.php", true, 302);
}
}
catch (PDOException $e)
{
echo $e->getMessage();
}
if ($error_pass) {
echo $error_pass;
}
}
else {
echo "Some fields are missing";
}
?>
<!DOCTYPE html>
<html>
<body>
<form method="post" action ="login.php">
<input type="text" name="email">
<input type="text" name="password">
<input type="submit" name="submit" value ="submit">
</form>
</body>
</html>
Remove password from your query. You need to find user only by email and then verify that password is correct.
$sql = $pdo-> prepare("SELECT * FROM users WHERE email = :email");
$sql->bindParam(':email', $email);
$sql->execute();
$req = $sql->fetch();
// #todo :: check did you got any users
if (password_verify($_POST["password"], $req['password'])) {
// password is valid
}
Related
I have a script that adds an email address and password to a table. I first search to see if the email address exists in the table. If it does, I give an error message. If it does not, I add the record.
Then, using mysqli_insert_id(), I run another query to update the record I just added, encrypting the password with md5.
But every time I run it, the record is added, but the password does not get updated with the md5 version of the password. I have echo'd the query and it shows that it should be updating the password with the encryption, but it doesn't. Any ideas?
<?php
session_start();
error_reporting(E_ALL);
if (array_key_exists("submit", $_POST)) {
$link = mysqli_connect("localhost", "eits_Admin", "WebSpinner1", "EITS_Sandbox");
if (!$link) {
die("Database connection error");
}
$error = '';
if (!$_POST['email']) {
$error .= "<br/>An email address is required";
}
if (!$_POST['password']) {
$error .= "<br/>A password is required";
}
if ($error != "") {
$error = "There were errors in your form - ".$error;
} else {
$query = "select id from secretdiary
where email = '".mysqli_real_escape_string($link, $_POST['email'])
."' limit 1";
// echo $query;
$result = mysqli_query($link, $query);
if (mysqli_num_rows($result) > 0) {
$error = "That email address is not available.";
} else {
$query = "insert into secretdiary
(email,password)
values ('" . mysqli_real_escape_string($link, $_POST['email'])
. "', '"
. mysqli_real_escape_string($link, $_POST['password']) . "')";
if (!mysqli_query($link, $query)) {
$error = "Could not sign you up at this time. Please try again later.";
} else {
$encPass = md5(md5(mysqli_insert_id($link)) . $_POST['password']);
$query = "update secretdiary
set password = '" . $encPass
. "' where id = " . mysqli_insert_id($link) . " limit 1";
echo $query;
$result = mysqli_query($link,$query);
echo "Sign up successful.";
}
}
}
}
?>
<div id="error"><? echo $error; ?></div>
<form method="post">
<input type="email" name="email" placeholder= "Your Email">
<input type="password" name="password" placeholder="Password">
<input type="checkbox" name="stayLoggedIn" value=1>
<input type="submit" name="submit" value="Sign Up!">
</form>
You've got a lot of lines of code for a relatively simple process. Personally your form error handling such as if it's empty (in this case) can be remedied by adding required at the end of each HTML form input element (This is what I'd do)
Secondly, md5 isn't safe for hashing passwords (you're hashing a password not encrypting it)
Thirdly here's a way to hash the password from the form using Bcrypt which is much better than using md5 hashing. So do whatever error checking you need to do before like counting the usernames and if row > 0 die('username exists) Example of full code at base using PDO
When checking the users login simply use password_verify() function to do so
Tidy code helps people on SO understand what your problem is and is generally nicer to read. I know you may just be looking for something that 'Does the job' But it helps you when debugging and us when you're asking for help.
I'm going to give you a way that is marginally more secure than your one.
index.php
<form method="post" id="regform" action="register.php">
<input type="text" name="username" placeholder="Enter your email Address"required/>
<input type="password" name="password" placeholder="Enter your password" required/>
<input type="submit" class="indexbttn" id="indexbttn" name="enter"value="enter"/>
</form>
connect.php
<?php
$servername = "localhost";
$dbusername = "root";
$dbpassword = "root";
$dbname = "fyp";
try{
$pdo = new PDO("mysql:host=$servername;dbname=$dbname",$dbusername, $dbpassword);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch(PDOException $e)
{
print "Error! Unable to connect: " . $e->getMessage() . "<br/>";
die();
}
?>
register.php
<?php
session_start();
require_once ('connect.php');
error_reporting(E_ALL);
ini_set('display_errors', 1);
if(isset($_POST['enter'])){
$username = !empty($_POST['username']) ? trim($_POST['username']) : null;
$pass = !empty($_POST['password']) ? trim($_POST['password']) : null;
$check (!filter_var($_POST['username'], FILTER_VALIDATE_EMAIL));
$cnt = "SELECT COUNT(username) AS num FROM users WHERE username = :username";
$stmt = $pdo->prepare($cnt);
$stmt->bindValue(':username', $username);
$stmt->execute();
$row = $stmt->fetch(PDO::FETCH_ASSOC);
if($row['num'] > 0){
die('That username already exists!');
}
$passHash = password_hash($pass, PASSWORD_BCRYPT, array("cost" => 12));
$insrt = "INSERT INTO users (username, password) VALUES (:username, :password)";
$stmt = $pdo->prepare($insrt);
$stmt->bindValue(':username', $username);
$stmt->bindValue(':password', $passHash);
$result = $stmt->execute();
if($result){
header( "refresh:5;url=index.php" );
echo 'You will be redirected in 5 seconds. If not, click here.';
}
}
?>
login.php
<?php
session_start();
require("connect.php");
if(isset($_POST['enter'])){
$username = !empty($_POST['username']) ? trim($_POST['username']) : null;
$pass = !empty($_POST['password']) ? trim($_POST['password']) : null;
$rtrv = "SELECT username, password, userid FROM users WHERE username = :username";
$stmt = $pdo->prepare($rtrv);
//Bind value.
$stmt->bindValue(':username', $username);
//Execute.
$stmt->execute();
//Fetch row.
$user = $stmt->fetch(PDO::FETCH_ASSOC);
//If $row is FALSE.
if($user === false){
//Could not find a user with that username!
die('Incorrect username');
}
else{
$validPassword = password_verify($pass, $user['password']);
if($validPassword){
$_SESSION['user_id'] = $user['username'];
$_SESSION['logged_in'] = time();
header( "Location: /protected.php" );
die();
} else{
die('Wrong password!');
}
}
}
?>
encrypt the password in the database with the following code:
$pas = $_POST['password'];
$pass = password_hash($pas, PASSWORD_BCRYPT);
in the solucioncontroller.php I try to verify the encrypted password but it does not work
class solucionController {
include_once 'model/solucion.php';
public function Login()
{
$solucion = new solucion();
if (isset($_POST["login"]) && isset($_POST["password"]))
{
$login = htmlentities(addslashes($_POST["login"]));
$password = htmlentities(addslashes($_POST["password"]));
$solucion = $this->model->Logeo($login, $password);
$pass= $this->model->getpass();
if (password_verify($password, $pass)&&$solucion == 1)
{
setcookie('usuario', $login, time() + 3600);
session_start();
$_SESSION["Usuario"] = $login;
header("Location: view/header.php");
header("Location: view/solucion/solucion.php");
header("Location: view/Footer.php");
}
}
header('Location: index.php');
return;
}
}
in the model solucion.php I search for the user and the password entered in the login view
class solucion {
public $res;
public function Logeo($login, $pass)
{
try {
$sql = "SELECT * FROM logeo WHERE usuario = :login AND pass = :password";
$resultado = $this->pdo->prepare($sql);
$resultado->bindValue(":login", $login);
$resultado->bindValue(":password", $pass);
$resultado->execute();
$numero_registro = $resultado->rowCount();
if ($numero_registro != 0)
{
return 1;
}
$this->res = $resultado->fetch(PDO::FETCH_ASSOC);
} catch (Exception $e) {
die($e->getMessage());
}
}
}
public function getpass(){
return $this->res['pass'];
}
in the login view is the form where you enter the username and password
<?php
if(isset($_COOKIE['usuario'])){
require 'view/solucion/solucion.php';
}
else{
?>
<a class="btn btn-success pull-right" href="?c=solucion&a=Invitado">Invitado</a>
<h1>Introduce tus datos</h1>
<form action="?c=solucion&a=Login" method="post">
<div class="container">
<label for="login"><b>Username</b></label>
<input type="text" placeholder="Ingrese usuario" name="login" required>
<label for="password"><b>Password</b></label>
<input type="password" placeholder="Ingrese ContraseƱa" name="password" required>
<button type="submit">Login</button>
</div>
</form>
<?php }?>
when entering the username and password, the data is deleted and I remain in the login view
You should fetch data using usuario only not using usuario and pass from database. Because password saved in database is hashed and can't be compared with simple text password entered by user. Change the model code as below:
class solucion {
public $res;
public function Logeo($login, $pass) {
try {
$sql = "SELECT * FROM logeo WHERE usuario = :login";
$resultado = $this->pdo->prepare($sql);
$resultado->bindValue(":login", $login);
$resultado->execute();
$numero_registro = $resultado->rowCount();
if ($numero_registro != 0) {
return 1;
}
$this->res = $resultado->fetch(PDO::FETCH_ASSOC);
} catch (Exception $e) {
die($e->getMessage());
}
}
}
public function getpass() {
return $this->res['pass'];
}
Also need to get password from request as:
$password = $_POST["password"];
instead of
$password = htmlentities(addslashes($_POST["password"]));
I am trying to improve my security by using password_hash and PDO prepared statements to prevent SQL Injection. I already worked with MySQLi OOP and Procedural. I am trying to shift to PDO and want to learn.
So I created a signup form using PDO which is already working and the encryption of password is working too. But when I logged in even with the correct username and password I can't login.
This is the code I use to hash my password in the sign up form.
$password = $_POST['password'];
$hash = password_hash($password, PASSWORD_DEFAULT);
Then I execute it using prepared statements. So no errors at here everything works fine.
But when I tried to login it won't redirect me to the landing page where it should be.
So here is the code to my login
<?php
session_start();
$host = "localhost";
$username = "root";
$password = "";
$database = "PDOtesting";
$message = "";
try
{
$connect = new PDO("mysql:host=$host; dbname=$database", $username, $password);
$connect->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
if(isset($_POST["login"]))
{
if(empty($_POST["username"]) || empty($_POST["password"]))
{
$message = '<label>All fields are required</label>';
}
else
{
$query = "SELECT * FROM users WHERE username = :username AND password = :password";
$statement = $connect->prepare($query);
$statement->execute(
array(
'username' => $_POST["username"],
'password' => $_POST["password"]
)
);
$count = $statement->rowCount();
if($count > 0)
{
$_SESSION["username"] = $_POST["username"];
header("location:login_success.php");
}
else
{
$message = '<label>Wrong Data</label>';
}
}
}
}
catch(PDOException $error)
{
$message = $error->getMessage();
}
?>
Should I include also the password_hash function that I included it in the signup and where should I place the code?
Don't try and match the password in the query, select the user, return and then use password_verify on the result.
Update:
<?php
...
try
{
$connect = new PDO("mysql:host=$host; dbname=$database", $username, $password);
$connect->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
if(isset($_POST["login"]))
{
if(empty($_POST["username"]) || empty($_POST["password"]))
{
$message = '<label>All fields are required</label>';
}
else
{
$query = "SELECT * FROM users WHERE username = :username LIMIT 1";
$statement = $connect->prepare($query);
$statement->execute(
array(
'username' => $_POST["username"]
)
);
$count = $statement->rowCount();
if($count > 0)
{
$result = $statement->fetch();
//check password
if (password_verify($_POST["password"], $result['password'])) {
$_SESSION["username"] = $_POST["username"];
exit(header("location:login_success.php"));
} else {
$message = '<label>Wrong Data</label>';
}
}
else
{
$message = '<label>Wrong Data</label>';
}
}
}
}
catch(PDOException $error)
{
$message = $error->getMessage();
}
?>
Here is what I did to signup, I am using meekrodb class:
session_start();
include "../includes/db.class.php";
if (!empty($_POST))
$username =$_POST["username"];
$pass =$_POST["password"];
$email =$_POST["email"];
$id_number =$_POST["id_number"];
$password = password_hash($pass, PASSWORD_DEFAULT);
$check = DB::query("SELECT * FROM tbs.credentials WHERE username=%s AND email=%s AND id_number=%s", $username, $email, $id_number);
if ($check)
{
echo '
<div class="medium medium-small red-text animated wobble">Account already exist</div>
<script> M.toast({html: \'Account already exists\'})</script>
<p class="medium medium-small teal-text">Click here to reset password</p>
';
} else {
$rows = array(
'username'=>$username,
'password'=>$password,
'email'=>$email,
'id_number'=>$id_number,
);
$validate = DB::insert('credentials', $rows);
if($validate) {
echo
'
<div class="medium medium-small green-text animated rubberBand">Account created</div>
<script> M.toast({html: \'Account created successful\'})</script>
';
}
}
}
For Loging in:
session_start();
include "../includes/db.class.php";
if (!empty([$_POST])) {
$username = $_POST['username'];
$password = $_POST['password'];
$check = DB::query("SELECT * FROM tbs.credentials where username=%s", $username);
if ($check)
{
$check_password= DB::query("SELECT password FROM tbs.credentials WHERE password=%s", $username);
if ($check_password){
password_verify($password, $check_password);
$_SESSION['username'] = $password;
echo "Login";
}
}
}
I am trying to login as user but don't know getting this error but when I try second time I will have access,But after login same this,and after logged in on second try I can't fetch email from DB it seems it not creating session.Its just passing the code not creating sessions.
if (!isset($_SESSION['email']) && isset($_POST['email'])) {
if (!empty($_POST['email']) && !empty($_POST['password'])) {
$email = filter_var($_POST['email'], FILTER_SANITIZE_STRING);
$password = filter_var($_POST['password'], FILTER_SANITIZE_STRING);
$password=sha1($password);
try {
$dbh = new PDO("mysql:host=$hostname; dbname=$database", $username, $pass);
$dbh -> setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$email = $_POST['email'];
$password = $_POST['password'];
$stmt = $dbh -> prepare("SELECT email, password FROM tbl_user WHERE email = '".$email."' and password = '".$password."'");
$stmt -> bindParam('".$email."', $email, PDO::PARAM_STR);
$stmt -> bindParam('".$password."', $password, PDO::PARAM_STR);
$stmt -> EXECUTE();
$em = $stmt -> fetchColumn();
if ($em == true) {
// session_register("email");
// session_register("password");
$_SESSION['email'] = $_POST['email'];
$_SESSION['START'] = time();
setcookie("username", $_POST['email'], mktime()+(60*3), "/");
setcookie("LUS", time(), mktime()+(60*3), "/");
$stmt -> $dbh -> prepare("SELECT Name FROM tbl_user WHERE email = '".$email."'");
$stmt -> EXECUTE();
$em2 = $stmt -> fetchColumn();
echo "Logged in.";
} else {
echo "email or password is incorrect.";
}
} catch (Exception $e) {
echo "".$e->getMessage();
}
} elseif (empty($_POST['email']) && !empty($_POST['password'])) {
# code...
echo "Error : Enter your E-mail.";
} elseif (!empty($_POST['email']) && empty($_POST['password'])) {
# code...
echo "Error: Enter your Password";
} else {
echo "Error: Enter your E-mail & Password";
}
}
elseif (isset($_SESSION['email'])) {
# code...
echo "Welcome again you still logged in <strong>" .round((time() . $_SESSION['START'])/60) ."</strong> minutes(s) ago <a href='logout.php'>LogOut</a>";
}
elseif (!isset($_SESSION['email'])) {
# code...
echo "You must loggin first.";
//header('location:../index.php');
}
change second prepare statment usage
$stmt -> $dbh -> prepare("SELECT Name FROM tbl_user WHERE email = '".$email."'");
to
$stmt = $dbh -> prepare("SELECT Name FROM tbl_user WHERE email = '".$email."'");
I have successfully created my passwords and am inserting them into the database using CRYPT_BLOWFISH. However I do no know how to match the crypted passwords in the database to the passwords the user is entering to login. Any help is greatly appreciated thanks.
To generate the password from the users input I use:
REGISTER.PHP
//If there are no errors or returned_records and the form is submitted let's submit the info and register the user
else if(!$error_msg && !$returned_record && $_POST['register']){
//Place the newly hased/encrypted password into our new_password variable
function generateHash($password_1){
if(defined("CRYPT_BLOWFISH") && CRYPT_BLOWFISH){
$salt = '$2y$11$'. substr(md5(uniqid(rand(), true)), 0, 22);
return crypt($password_1, $salt);
}//End If
}//End Function genrateHash*/
$new_password = generateHash($password_1);
$pass = $new_password;
//Build our query
$sql = ("INSERT INTO members (username, email, password_1) VALUES (?,?,?)");
//Prepare our query
$stmt = $mysqli->prepare($sql) or die("Failed Execution");
//Bind the fields and there paramters to our query
$stmt->bind_param('sss', $username, $email, $new_password);
//Execute the query
$stmt->execute();
echo $stmt->error;
header('Location: http://www.yourschoolsincanada.com/english/register/registration-success/');
exit();
}
LOGIN.PHP
if(isset($_POST['login'])){
$username = $_POST['username'];
$password_1 = $_POST['password_1'];
$sql = "SELECT member_id, username, password_1 FROM members WHERE username = ? AND password_1 = ? LIMIT 1";
//Prepare our query
if($stmt = $mysqli->prepare($sql)){
//Bind the Parameters to the query
$stmt->bind_param('ss', $username, $password_1);
//Execute the query
$result = $stmt->execute();
/*Store our result to get properties*/
$stmt->store_result();
//Get the number of rows
$num_of_rows = $stmt->num_rows;
//Bind the results of what the query gave us to our three variables
$stmt->bind_result($id, $username, $password_1);
if(crypt($password_1, $pass) == $pass){
echo "Match";
}
else{
echo "Passwords don't match";
}
}
Working Demo
I've gotten the following to work. The HTML form and PHP all run inside the same page.
<?php
DEFINE ('DB_USER', 'xxx');
DEFINE ('DB_PASSWORD', 'xxx');
DEFINE ('DB_HOST', 'xxx');
DEFINE ('DB_NAME', 'xxx');
$mysqli = #mysqli_connect (DB_HOST, DB_USER, DB_PASSWORD, DB_NAME)
OR die("could not connect");
if(isset($_POST['login'])){
$username = htmlentities(trim($_POST['username']));
$username = mysqli_real_escape_string($mysqli, $username);
$password = trim($_POST['password']);
$query = mysqli_query($mysqli, "SELECT username, password_1 FROM members WHERE username = '$username'");
$row = mysqli_fetch_assoc($query);
$numrows = mysqli_num_rows($query);
$dbuser = $row['username'];
$dbpass = $row['password_1'];
$hashed_password = crypt($password, $dbpass);
// var_dump($dbuser); // For testing purposes only, can be removed
echo "<hr>";
// var_dump($dbpass); // For testing purposes only, can be removed
if( ($username == '') || ($password == '') ) {
$error_string = '<font color=red>You have left either the username or password field blank!</font>';
echo $error_string;
}
if ($numrows == 0)
{
$error_string = '<font color=red>No username can be found!</font>';
echo $error_string;
}
else if ($numrows == 1)
{
if ($hashed_password == $dbpass)
{
$error_string = '<font color=red>Details checked out</font>';
echo $error_string;
}
}
else {
$error_string = '<font color=red>There was an error. Please contact an Admin</font>';
echo "SORRY Charlie!";
}
} // brace for isset login
?>
<form action="" method="post">
Username:
<input type="text" name="username">
<br>
Password:
<input type="text" name="password">
<br>
<input type="submit" name="login" value="Submit">
</form>
Original answer
The following should work, since I've gotten a "match" using the following inside the same file.
Read the comments inside the code.
<?php
$password_1 = "1234567890"; // User-entered password
function generateHash($password_1){
if(defined("CRYPT_BLOWFISH") && CRYPT_BLOWFISH){
$salt = '$2y$11$'. substr(md5(uniqid(rand(), true)), 0, 22);
return crypt($password_1, $salt);
}
}
// Remove the echo. For testing purposes only
echo $new_password = generateHash($password_1);
$pass = $new_password;
echo "<br>";
echo $pass;
echo "<hr>";
// Verify that the password matches and use in your login page
// Syntax: if(crypt($password_entered, $password_hash) == $password_hash)
if(crypt($password_1,$pass) == $pass) {
// password is correct
echo "Match.";
}
else {
echo "No match.";
}
EDIT
Password generator:
<?php
$password_1 = "1234567890"; // User-entered generated password
// or from a form
// $password_1 = $_POST['password']; // User-entered generated password
function generateHash($password_1){
if(defined("CRYPT_BLOWFISH") && CRYPT_BLOWFISH){
$salt = '$2y$11$'. substr(md5(uniqid(rand(), true)), 0, 22);
return crypt($password_1, $salt);
}
}
// here you can enter the password into DB
// since we have a successful echo
// Remove the echo. For testing purposes only
echo $new_password = generateHash($password_1);
$pass = $new_password;
echo "<br>";
echo $pass;
echo "<hr>";
Login check:
$password_1 = $_POST['password']; // User-entered password
// DB codes example:
$query = mysqli_query($con, "SELECT password FROM users WHERE password='".$password_1."'");
// Verify that the password matches and use in your login page
// Syntax: if(crypt($password_entered, $password_hash) == $password_hash)
if(crypt($password_1,$pass) == $pass) {
// password is correct
echo "Match.";
}
else {
echo "No match.";
}