This question already has answers here:
Where to put password_verify in login script?
(2 answers)
Closed 7 years ago.
Below is a simple registration script using php, I obviously want to store peoples data securely. I was wondering where would be the best place to implement the hashing script? Would it be implemented in the script below or have it alone?
<?php
//values to be inserted in database table
//session_start();
include('connect.php');
$email = $_POST['email'];
$password= $_POST['password'];
$username= $_POST['username'];
$query = "INSERT INTO users (username, email, password) VALUES(?, ?, ?)";
$statement = $mysqli->prepare($query);
//bind parameters for markers, where (s = string, i = integer, d = double, b = blob)
$statement->bind_param('sss', $username, $email, $password);
if($statement->execute()){
print 'Success! ID of last inserted record is : ' .$statement->insert_id .'<br />';
}else{
die('Error : ('. $mysqli->errno .') '. $mysqli->error);
}
$statement->close();
?>
Another thing, when fetching peoples information from the database so they can sign in do I fetch their hashed password or do I have to recreate a hashed version of the password they've entered? I've read different ways of doing it, I just want to know the most secure. Thank you
EDIT:
This is my login code
<?php
include 'connect.php';
if ( !isset($_POST['username'], $_POST['password']) ) {
// Could not get the data that should have been sent.
die ('Username and/or password does not exist!');
}
// Prepare our SQL
if ($stmt = $mysqli->prepare('SELECT password FROM users WHERE username = ?')) {
// Bind parameters (s = string, i = int, b = blob, etc), hash the password using the PHP password_hash function.
$stmt->bind_param('s', $_POST['username']);
$stmt->execute();
$stmt->store_result();
// Store the result so we can check if the account exists in the database.
if ($stmt->num_rows > 0) {
$stmt->bind_result($password);
$stmt->fetch();
// Account exists, now we verify the password.
if (password_verify($_POST['password'], $password)) {
// Verification success! User has loggedin!
echo 'You have logged in!';
} else {
echo 'Incorrect username and/or password!';
}
} else {
echo 'Incorrect username blar password!';
}
$stmt->close();
} else {
echo 'Could not prepare statement!';
}
?>
ANSWER:
<?php
//values to be inserted in database table
//session_start();
include('connect.php');
//Fixed cost of 10 to fit server req
//Random salt to be added to the pass
$options = [
'cost' => 10,
'salt' => mcrypt_create_iv(22, MCRYPT_DEV_URANDOM),
];
$email = $_POST['email'];
$password= password_hash($_POST['password'], PASSWORD_BCRYPT, $options);
$username= $_POST['username'];
$query = "INSERT INTO users (username, email, password) VALUES(?, ?, ?)";
$statement = $mysqli->prepare($query);
//bind parameters for markers, where (s = string, i = integer, d = double, b = blob)
$statement->bind_param('sss', $username, $email, $password);
if($statement->execute()){
print 'Success! ID of last inserted record is : ' .$statement->insert_id .'<br />';
}else{
die('Error : ('. $mysqli->errno .') '. $mysqli->error);
}
$statement->close();
?>
While putting Users value into the variable is the perfect time to sanitize
It would be great if you use a Global function to sanitize data and use that function everywhere
Here is an Example of secure code (without OOP ):
<?php
// create a globa function
//
function string_sanitize($value) {
$search = array("\\", "\x00", "\n", "\r", "'", '"', "\x1a");
$replace = array("\\\\","\\0","\\n", "\\r", "\'", '\"', "\\Z");
return str_replace($search, $replace, $value);
}
function sanitize($value){
return $this->string_sanitize(htmlentities(trim($value)));
}
//values to be inserted in database table
//session_start();
include('connect.php');
$email = sanitize($_POST['email']);
$username = sanitize($_POST['username']);
// Sanitize password using hash()
$password = hash('sha256', $_POST['password']);
$query = "INSERT INTO users (username, email, password) VALUES(?, ?, ?)";
$statement = $mysqli->prepare($query);
//bind parameters for markers, where (s = string, i = integer, d = double, b = blob)
$statement->bind_param('sss', $username, $email, $password);
if($statement->execute()){
print 'Success! ID of last inserted record is : ' .$statement->insert_id .'<br />';
}else{
die('Error : ('. $mysqli->errno .') '. $mysqli->error);
}
$statement->close();
?>
Related
This question already has answers here:
How to use PHP's password_hash to hash and verify passwords
(5 answers)
Closed 2 years ago.
I've a problem with my php login file. I ask the password from my db by checking the email. When I obtain this password I check it with the password the user filled in.
In the password_verify($Passwd, $row['Passwd']) the result will always return 0 but the result should be return 1 (password matches).
Why do my passwords not match with each other?
Login code:
<?php
if(isset($_POST['submit'])){
include_once '../includes/connection.php';
$Email = $_POST['email'];
$Passwd = $_POST['passwd'];
//Create Template
$sql = "SELECT Passwd FROM user WHERE Email = ?";
//Create Prepared Statement
$stmt = mysqli_stmt_init($conn);
//Prepare Prepared Statement
if(!mysqli_stmt_prepare($stmt, $sql)){
echo "SQL Statement Failed";
} else {
mysqli_stmt_bind_param($stmt, "s", $Email);
mysqli_stmt_execute($stmt);
$res = mysqli_stmt_get_result($stmt);
while ($row = mysqli_fetch_assoc($res)){
echo $Passwd . "<br>";
echo $row['Passwd'];
if(password_verify($Passwd, $row['Passwd'])){
echo "1";
} else {
echo "0";
}
}
}
} else {
header("Location: ../index.php?login=error");
}
?>
Registration code:
<?php
if(isset($_POST['submit'])){
include_once '../includes/connection.php';
$Username = $_POST['username'];
$Email = $_POST['email'];
$Passwd = $_POST['pwd'];
//Create Template
$sql = "INSERT INTO user (Username, Email, Passwd)
VALUES (?, ?, ?);";
//Create Prepared Statement
$stmt = mysqli_stmt_init($conn);
//Prepare Prepared Statement
if (!mysqli_stmt_prepare($stmt, $sql)) {
echo "SQL Statement Failed";
} else {
$hashed_passwd = password_hash($Passwd, PASSWORD_DEFAULT);
//Replace '?' by the acctual data
mysqli_stmt_bind_param($stmt, "sss", $Username, $Email, $hashed_passwd);
//Run parameters inside database
mysqli_stmt_execute($stmt);
}
header("Location: ../index.php?signup=succes");
} else {
header("Location: ./index.php?sinup=error");
}
?>
Passwd is a varchar(50) column in the database.
The password_hash manual says:
it is recommended to store the result in a database column that can expand beyond 60 characters (255 characters would be a good choice)
So you need to specify a minimum size of 60 characters for the password column in your database - but a larger size e.g. 255 is recommended in case the default hashing algorithm changes in future.
You'll also need to re-generate any existing passwords stored in the 50-character field, because they will have been truncated when they were saved, and the extra information has been lost, meaning those old passwords can never be verified.
This code gets through all of the debugs but for some reason, it is still not inserting. It tries to check if the username already exists in the database and if it doesn't, it adds it. For some reason, it still doesn't add it to the data table. It does get to the insert part but it doesn't add a row.
<?php
require "conn.php";
echo "debug 1";
$stmt = $conn->prepare("SELECT * FROM UserData WHERE username = ?");
$stmt->bind_param('s', /*$_POST["username"]*/ $username );
$username = 'hi';
$stmt->execute();
$stmt->store_result();
echo "debug 2";
if ($stmt->num_rows == 0){ // username not taken
echo "debug 3";
$stmt2 = $conn->prepare("INSERT INTO UserData (username, password) VALUES (?, ?)");
$password =(/*$_POST["password"]*/ "hey");
$username =(/* $_POST["username"]*/ "hi");
$stmt2->bind_param('s',$username);
$stmt2->bind_param('s',$password);
$stmt2->execute();
if ($stmt2->affected_rows == 1){
echo 'Insert was successful.';
}else{ echo 'Insert failed.';
var_dump($stmt2);
}
}else{ echo 'That username exists already.';}
?>
You should bind all variables once with bind_param() and not twice or N times. The correct way is pass first the types followed by the variables.
change:
$stmt2->bind_param('s',$username);
$stmt2->bind_param('s',$password);
By
$stmt2->bind_param('ss',$username, $password);
With php5.6 >= you can pass an array with ... operator to simplify.
$data = array('user' => 'someUser', 'password' => 'secret');
$stmt2->bind_param('ss', ...$data);
I am trying to insert form data into mysql database but it is not inserted into table and there is no error!
Here is my code
<?php
$con = mysqli_connect('localhost', 'root', '', 'register');
if (isset($_POST['submit'])) {
$shop = $_POST['shopname'];
$name = $_POST['name'];
$user = $_POST['username'];
$email = $_POST['email'];
$password = $_POST['password'];
$repassword = $_POST['repassword'];
$phone = $_POST['phone'];
$sql = "INSERT INTO registration (shop_name,name,username,email,password,repassword,phone) VALUES ('$shop','$name''$user','$email','$password','$repassword','$phone')";
if (mysqli_query($con, $sql)) {
echo "Signup Sucessfull";
} else {
echo mysqli_error();
}
}
?>
How can I resolve this problem?
Turns out you forgot to mention a comma after the name.
'$name''$user' // Missing comma in between
Also, it should be mysqli_error($con) instead of mysqli_error()
Try some debugging:
$sql = "INSERT INTO registration (shop_name,name,username,email,password,repassword,phone) VALUES ('".$shop."','".$name."', '".$user."','".$email."','".$password."','".$repassword."','".$phone."')";
mysqli_query($con, $sql) or die(mysqli_error($con));
You seems to miss "," between the insert values. This code will work fine.
<?php
$con = mysqli_connect('localhost', 'root', '', 'register');
if (isset($_POST['submit'])) {
$shop = $_POST['shopname'];
$name = $_POST['name'];
$user = $_POST['username'];
$email = $_POST['email'];
$password = $_POST['password'];
$repassword = $_POST['repassword'];
$phone = $_POST['phone'];
$sql = "INSERT INTO registration (shop_name,name,username,email,password,repassword,phone) VALUES ('".$shop."','".$name."','".$user."','".$email."','".$password."','".$repassword."','".$phone."')";
if (mysqli_query($con, $sql)) {
echo "Signup Sucessfull";
} else {
die(mysqli_error($con));
}
}
?>
Yes, As already #ObjectManipulator pointed your silly mistake
near '$name''$user'.
I will strongly recommend you to use mysqli_prepare to avoid SQL Injection.
<?php
$con = mysqli_connect('localhost', 'root', '', 'register');
if (isset($_POST['submit'])) {
$stmt = mysqli_prepare($con, "INSERT INTO registration (shop_name,name,username,email,password,repassword,phone) VALUES (?, ?, ?, ?,?, ?, ?)");
mysqli_stmt_bind_param($stmt, 'sssssss',$_POST['shopname'],$_POST['name'],$_POST['username'],$_POST['email'],$_POST['password'],$_POST['repassword'],$_POST['phone']);
if (mysqli_stmt_execute($stmt)) {
echo "Signup Sucessfull";
} else {
echo mysqli_error($con);
}
}
?>
And, as #JonStirling suggested not to store password in plain text
and use any Password API to encrypt password.
There are many ways to encrypt your password. Use anyone of them. Right now, I illustrated with md5().
And, Why to store password and repassword in database table. While storing user data into database table, check there itself if password & repassword matches or not.
Just a suggestion. It's upto you to choose.
<?php
$con = mysqli_connect('localhost', 'root', '', 'register');
if (isset($_POST['submit'])) {
if(isset($_POST['password']) && isset($_POST['repassword']) && ($_POST['password'] == $_POST['repassword'])){
$stmt = mysqli_prepare($con, "INSERT INTO registration (shop_name,name,username,email,password,phone) VALUES (?, ?, ?, ?, ?, ?)");
mysqli_stmt_bind_param($stmt, 'ssssss',$_POST['shopname'],$_POST['name'],$_POST['username'],$_POST['email'],md5($_POST['password']),$_POST['phone']);
if (mysqli_stmt_execute($stmt)) {
echo "Signup Sucessfull";
} else {
echo mysqli_error();
}
} else {
echo "Password must match.";
}
}
?>
else {
echo mysqli_error($con);
}
Problem solved. You forgot the connection details $con for your MySQL error output. This will now correctly output your MySQL Syntax mistakes from your query.
Other Notes:
Use Prepared statements for MySQLi (link)
Use a proper Password hashing algorithm such as Password_hash. Do not use MD5 (it's too fast and has too many collisions) and NEVER store passwords as plaintext.
Use the various filter_Var on your POSTed variables to clean them and make sure you catch any invalid data (such as improper email addresses)
Put comma in your sql query as below
$sql = "INSERT INTO registration (shop_name,name,username,email,password,repassword,phone)VALUES
('$shop','$name','$user','$email','$password','$repassword','$phone')";
The script is already working fine but I want to insert a command that allows only if the username is not yet used.
if (isset($_POST['submit'])) {
$firstname = htmlentities($_POST['firstname'], ENT_QUOTES);
$lastname = htmlentities($_POST['lastname'], ENT_QUOTES);
$position = htmlentities($_POST['position'], ENT_QUOTES);
$username = htmlentities($_POST['username'], ENT_QUOTES);
$password = htmlentities($_POST['password_two'], ENT_QUOTES);
$uniqid = uniqid('', true);
if ( $firstname == '' || $lastname == '' || $position == '' || $username == '' || $password == '') {
$error = 'ERROR: Please fill in all required fields!';
renderForm($error, $firstname, $lastname, $position, $username, $password);
} else {
if ($stmt = $connection->prepare("INSERT INTO employee (uniqid, firstname, lastname, position, username, password) VALUES (?, ?, ?, ?, ?, ?)")) {
$stmt->bind_param("ssssss", $uniqid, $firstname, $lastname, $position, $username, $password);
$stmt->execute();
$stmt->close();
} else {
echo "ERROR: Could not prepare SQL statement.";
}
header("Location: regemployee.php");
}
} else {
renderForm();
}
Make username unique on the DB, then when you try to insert the same username in to the DB again, the insert will through an error.
Alternatively you could do a SELECT * FROM employee WHERE username = ? and check if results is > 0.
Then you would know it exists already.
Do another SELECT query which checks if the submitted username already exist:
$stmt = $connection->prepare("SELECT * FROM employee WHERE username = ?");
$stmt->bind_param("s", $username);
$stmt->execute();
Then get the number of results:
$stmt->store_result();
$noofres = $stmt->num_rows;
$stmt->close();
Then, create a condition that if it yet doesn't exist, it will do the insert query:
if($noofres == 0){
/* INSERT QUERY HERE */
} else {
echo 'Username already taken.';
}
My code works, if I wish to insert into the database, but my checking whether the user already exists doesn't work.
*I thought the idea was to check if a row exists already with that username, if so don't add that user to the database, else
$email = $_POST['email'];
$password= password_hash($_POST['password'], PASSWORD_BCRYPT, $options);
$username= $_POST['username'];
$result = mysqli_query($mysqli, "SELECT username FROM users WHERE username = '$username'");
$row_count = $result->num_rows;
if($row_count == 1){
echo'User exists';
}else{
$query = "INSERT INTO users (username, email, password) VALUES(?, ?, ?)";
$statement = $mysqli->prepare($query);
//bind parameters for markers, where (s = string, i = integer, d = double, b = blob)
$statement->bind_param('sss', $username, $email, $password);
if($statement->execute()){
print 'Success! ID of last inserted record is : ' .$statement->insert_id .'<br />';
}else{
die('Error : ('. $mysqli->errno .') '. $mysqli->error);
}
$statement->close();
}
You have mixed the Procedural style & Object oriented style for executing the query.
When using,
1) Procedural Style
$result = mysqli_query($mysqli, "Your Query");
use this, $row_count = mysqli_num_rows($result);
2)Object oriented style
$result = $mysqli->query("Your Query");
Use this, $row_count = $result->num_rows;
So, According to your code, You are using Object Oriented Style. So, you need to change
$result = mysqli_query($mysqli,"SELECT username FROM users WHERE username = '$username'");
to
$result = $mysqli->query("SELECT username FROM users WHERE username = '$username'");
Edited Code.
$email = $_POST['email'];
$password= password_hash($_POST['password'], PASSWORD_BCRYPT, $options);
$username= $_POST['username'];
$result = $mysqli->query("SELECT username FROM users WHERE username = '$username'");
$row_count = $result->num_rows;
if($row_count == 1)
{
echo 'User exists';
}
else
{
$query = "INSERT INTO users (username, email, password) VALUES(?, ?, ?)";
$statement = $mysqli->prepare($query);
//bind parameters for markers, where (s = string, i = integer, d = double, b = blob)
$statement->bind_param('sss', $username, $email, $password);
if($statement->execute())
{
print 'Success! ID of last inserted record is : ' .$statement->insert_id .'<br />';
}
else
{
die('Error : ('. $mysqli->errno .') '. $mysqli->error);
}
$statement->close();
}
For more info, check this mysqli_num_rows vs ->num_rows
$db = ("SELECT username FROM userlist WHERE username='$username'");
$query = $conn->query($db);
if(mysqli_fetch_array($query) > 0 ) { //check if there is already an entry for that username
echo "Username already exists!";
}