<?php
session_start();
//Obtain data from register page
$email = $_POST['email'];
$password = $_POST['password'];
//Check to see user has input
if ($username !='' || $password !='' || $confirmpassword !='' || $email !='') {
if ($password1 == $password2) {
// connect to database
$db = new mysqli('removed', 'removed','removed' ,'removed');
// Check to see if connection was successful
if ($db->connect_errorno) {
die ('Sorry, we are having some issues with our database. We should be back online soon.');
}
// Prepare statement
$query = "INSERT INTO `database`.`users` (
`id` ,
`minecraftusername` ,
`email` ,
`password` ,
`joined` ,
`rank`
)
VALUES (
NULL , ?, ?, ?, NOW( ) , '1'
);";
$stmt=$db->prepare($query);
$stmt->bind_param('sss', $username, $email, $password);
//Execute query
$stmt->execute();
// header("Location: ../default.php");
echo 'You have successfully registered an account!';
} else {
// header("Location: ../default.php");
echo 'Passwords do not match.';
}
} else {
// header("Location: ../default.php");
echo 'Please fill out all the fields';
}
?>
When you try to register, it does echo the registered successfully message, but when I go to phpmyadmin the number of rows hasn't changed.
I am really not sure what errors I have made.
Any help would really be appreciated.
$password = $_POST['password'];
Here you set only $password, but then you expect other variables to exist,
if ($username !='' || $password !='' || $confirmpassword !='' || $email !='') {
if ($password1 == $password2) {
$confirmpassword and $password1 and $password2 are never set. Noted in comments by #RobP and #Ali.
You connect to the database only if $password1 == $password2, and you only die() in that block as well. So you might easily skip that whole block, and not die(), and go on to try to run the INSERT without having connected to the database. Noted in comment from #Erico.
if ($db->connect_errorno) {
It's connect_errno, not "connect_errorno". If that block of code were run, it would generate a notice: PHP Notice: Undefined property: mysqli::$connect_errorno. So this proves that your code to connect to the database was never run.
$stmt=$db->prepare($query);
$stmt->bind_param('sss', $username, $email, $password);
$stmt->execute();
You should always check the return value of prepare() and execute(). They return false if there is any problem with the statement. Like if you had a syntax error, or violated a unique constraint or something. Right now your INSERT might be failing but you'll never know. Also noted in a comment by #sanketh.
Or else you can set mysqli_report(MYSQLI_REPORT_STRICT) to raise exceptions if there's an error. Then you don't need to write code to check the return values, because your script will die if there's any mysqli error. You have to set this report mode before you connect to the database.
Also, you never set a value for $username.
Related
Hello guys i have a simple pdo login and register page, and when i test it in localhost, I could register same usernames and emails. How do i check for duplication in registration page, and shows an error if same user/email already exist? This is my register.php
<?php
require 'config.php';
if(isset($_SESSION['username'])){
header('location:dashboard.php');
}
if(isset($_POST['register'])) {
$errMsg = '';
// Get data from FROM
$fullname = $_POST['fullname'];
$username = $_POST['username'];
$address = $_POST['address'];
$password = $_POST['password'];
$secretpin = $_POST['secretpin'];
if($fullname == '')
$errMsg = 'Enter your fullname!';
if($username == '')
$errMsg = 'Enter username!';
if($address == '')
$errMsg = 'Enter a valid email!';
if($password == '')
$errMsg = 'Enter password!';
if($secretpin == '')
$errMsg = 'Enter a sercret pin number!';
if($errMsg == ''){
try {
$stmt = $connect->prepare('INSERT INTO pdo (fullname, username, address, password, secretpin) VALUES (:fullname, :username, :address, :password, :secretpin)');
$stmt->execute(array(
':fullname' => $fullname,
':username' => $username,
':address' => $address,
':password' => $password,
':secretpin' => $secretpin,
));
header('Location: register.php?action=joined');
exit;
}
catch(PDOException $e) {
echo $e->getMessage();
}
}
}
if(isset($_GET['action']) && $_GET['action'] == 'joined') {
$errMsg = 'Registration successfull. Now you can login';
}
?>
And my other problem is, how to get the registration date of every person who register and save in the database and echo the date in the profile page. Im just a newbie in php and i get some ideas in other open source php codes. Thanks guys.
P.S dont mind about the security, Im still learning about that :)
Your security is already slightly enhanced by the fact you are using PDO rather than the deprecated mysql or mysqli.
Checking for duplication is simply a case of an SQL "LIKE" statement query - like so -
SELECT * FROM websiteUsers WHERE userEmail or userLogin LIKE ?
an example of this can actually be found on this link - https://www.w3schools.com/sql/sql_like.asp
I would not want to undermine your approach, however bear in mind that at the moment your code here:
if($fullname == '')
$errMsg = 'Enter your fullname!';
if($username == '')
$errMsg = 'Enter username!';
if($address == '')
$errMsg = 'Enter a valid email!';
if($password == '')
$errMsg = 'Enter password!';
if($secretpin == '')
$errMsg = 'Enter a sercret pin number!';
will overwrite the $errMsg everytime, so you won't get the full set of errors either, which might or might not be important.
I know you didn't want security pointers as such, but using
if(isset($_GET['action']) && $_GET['action'] == 'joined') {
as a way of knowing if someone is registered is not a good idea either, please either use a framework or change your approach, as this one suggests I can access that url without actually filling out your form.
This question already has answers here:
How can I prevent SQL injection in PHP?
(27 answers)
Closed 4 years ago.
I am learning how to use prepared statements in my simple login system to make it more secure.
I have followed a few different tutorials to get it working but cant get it to work. When i enter the username and password wrong it gives me the error. When i enter the username and password correct i still get the error.
What am i doing wrong?
I am new to this so apologies for any obvious errors.
I have also looked into hashing my password as it is being stored as plain text in the database at the moment but that will be my next step after i get this working.
Here is my code:
<?php
error_reporting(E_ALL); ini_set('display_errors', 1);
session_start(); // Starting Session
$error=''; // Variable To Store Error Message
if($SERVER['REQUESTMETHOD'] == 'POST') {
if (empty($POST['username']) || empty($POST['password'])) {
$error = "Enter Username and Password";
}
else
{
// Define $username and $password
$username = $_POST['username'];
$password = $_POST['password'];
//connect to database
include('dbconx.php');
}
$stmt = $con->prepare("SELECT * from admin where password=? AND username=?");
$stmt->bind_param('ss', $username, $password);
$stmt->execute();
$stmt->bind_result($id, $username, $password);
$stmt->store_result();
if($stmt->num_rows == 1) //To check if the row exists
{
$_SESSION['login_user'] = $username; // Initializing Session
header("location: confirm.php"); // Redirecting To Other Page
}
else {
$error = "Username or Password is incorrect";
}
mysqli_close($con); // Closing Connection
}
?>
You have your bound parameter arguments backwards. Your query binds password then username but your bind_param() uses $username then $password.
I've never been a fan of using the number of rows returned to determine existence. Instead, you can simply use fetch(). It will return a boolean value indicating whether or not there was a result.
For example
$stmt = $con->prepare('SELECT id from admin where password = ? AND username = ?');
$stmt->bind_param('ss', $password, $username); // note the order
$stmt->execute();
$stmt->bind_result($id);
if ($stmt->fetch()) {
$_SESSION['login_user'] = $username;
$_SESSION['login_user_id'] = $id; // probably important
header("Location: confirm.php");
exit; // always exit after a "Location" header
} else {
$error = "Username or Password is incorrect";
}
mysqli_stmt::store_result should be called before mysqli_stmt::bind_result, also you would need to call mysqli_stmt::seek_data and mysqli_stmt::fetch to get the result.
Example :
<?php
$db = new Mysqli(...);
$inputUsername = $_POST['username'] ?? '';
$inputPassword = $_POST['password'] ?? '';
$statment = $db->prepare('SELECT `id`,`username`,`password` FROM `admin` WHERE `username` = ?');
$statment->bind_param('s',$inputUsername);
$statment->execute();
$statment->store_result();
$statment->bind_result($id,$username,$password);
if($statment->num_rows) {
$statment->data_seek(0);
$statment->fetch();
/**
* this is not secure
* #see http://php.net/manual/en/function.password-hash.php
*/
if($inputPassword === $password) {
echo sprintf('Welcome, %s!',$username);
} else {
echo 'Incorrect password!';
}
} else {
echo sprintf('No such user with the given username (%s)',$inputUsername);
}
$statment->close();
$db->close();
Removed bind_result and store_result for get_result and fetch_assoc. It makes getting db records more flexible and stable.
Also added exit(); after redirection so no other codes will be executed after redirect command.
Typo in:
if (empty($POST['username']) || empty($POST['password']))
^ $POST should be $_POST instead.
$error is not being checked properly if empty or not. And still goes through mysqli functions block even if there is an error. Fixed that by creating an appropriate if statement that encloses the mysqli funtions block.
Also added proper indentation to the code for readability.
New Code:
<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);
session_start(); // Starting Session
$error=''; // Variable To Store Error Message
$_POST['username'] = isset( $_POST['username'] ) ? $_POST['username'] : '';
$_POST['password'] = isset( $_POST['password'] ) ? $_POST['password'] : '';
if($_SERVER['REQUEST_METHOD'] == 'POST') {
if (empty($_POST['username']) || empty($_POST['password'])) {
$error = "Enter Username and Password";
}
else{
// Define $username and $password
$username = $_POST['username'];
$password = $_POST['password'];
//connect to database
include('dbconx.php');
}
if( $error == "" ) {
$stmt = $con->prepare("SELECT * from students where username=? AND password=?");
$stmt->bind_param('ss', $username, $password);
$stmt->execute();
$result = $stmt->get_result();
if($result->num_rows == 1) {
$row = $result->fetch_assoc();
$_SESSION['login_user'] = $row['username']; // Initializing Session
header("location: confirm.php");exit(); // Redirecting To Other Page
}
else {
$error = "Username or Password is incorrect";
}
mysqli_close($con); // Closing Connection
}
echo $error;
}
?>
I have some issues with my code. It seems like I'm not able to have multiple prepared statements which seems a little unusual to me.
I would be glad if you can spot an error or help me because I can't figure out the issue.
My error:
Fatal error: Call to a member function bind_param() on boolean in /Applications/XAMPP/xamppfiles/htdocs/platform/creating_user.php on line 37
I am trying to check if the users email already exists in the database and then register the user.
The code works fine when i dont execute the $check.
$check->execute();
I would also like some response on my workflow (the way my code is built up). is it okay?
Thanks!
<?php
$db = new mysqli("localhost","root","","database");
session_start();
if (isset($_POST)){
if(
!empty($_POST["name"])
& !empty($_POST["city"])
& !empty($_POST["zip"])
& !empty($_POST["email"])
& !empty($_POST["tel"])
& !empty($_POST["password"])
) {
$name = encrypt($_POST["name"]);
$city = encrypt($_POST["city"]);
$zip = encrypt($_POST["zip"]);
$email = encrypt($_POST["email"]);
$tel = encrypt($_POST["tel"]);
$password = encrypt($_POST["password"]);
if(!empty($name) && !empty($city) && !empty($zip) && !empty($email) && !empty($tel) && !empty($password)) {
$check = $db->prepare("SELECT email FROM user WHERE email = ?");
$check->bind_param('s', $email);
$check->execute();
if ($check->num_rows == 1) {
header("Location: index.php");
die();
} else {
$insert = $db->prepare("INSERT INTO user (name, city, zip, email, tel, password, created) VALUES (?, ?, ?, ?, ?, ?, NOW())");
$insert->bind_param("ssssss",$name, $city, $zip, $email, $tel, $password);
if ($insert->execute()){
$db->close();
$_SESSION["user"] = $email;
header("Location: created_user");
die();
} else {
header("Location: create-user");
die();
}
}
} else {
header("Location: create-user");
die();
}
} else {
header("Location: create-user");
die();
}
} else {
header("Location: create-user");
die();
}
?>
On php.net I found this
mysqli::prepare() returns a statement object or FALSE if an error
occurred.
So this mean something is wrong with your $db object. This could be:
Wrong password
Wrong username
...
Hei guys, I have been working around to figure out what's wrong here but unable to identify it. I am creating a login page and here the code. Could you please help me to identify it?thnx
<?php include 'db.php'; ?>
<?php
if (isset($_POST['login'])) {
$username = $_POST['username'];
$password = $_POST['password'];
$username = mysqli_real_escape_string($connection, $username);
$password = mysqli_real_escape_string($connection, $password);
$query = "SELECT * FROM tbl_users WHERE username = '{$username}' ";
$login_query = mysqli_query($connection, $query);
while ($row = mysqli_fetch_assoc($login_query)) {
$db_username = $row['username'];
$db_password = $row['password'];
$firstname = $row['firstname'];
$lastname = $row['lastname'];
$email = $row['email'];
$db_role = $row['role'];
if ($username !== '{$db_username}' && $password !== '{$db_password}' ) {
header("Location: ../index.php");
}elseif ($username == '{$db_username}' && $password == '{$db_password}') {
header("Location: ../admin");
} {
header("Location: ../index.php");
}
}
}
?>
Why are you using $username !== '{$db_username}' while you can use $username !== $db_username directly? It isn't necessary to use quotes when you are comparing strings without any modification...
Also, if you want to parse variables within quotes, DON'T use single quotes, because them will not be parsed by PHP. Using single quotes you are always comparing $username with '{$db_username}'. Instead, use double quotes which will be parsed by PHP.
Here's an example of what i'm saying:
<?php
$db_username = 'admin';
$username = $_POST['username']; // asumming it is 'admin'
if($username == '{$db_username}') // will be false because 'admin' != '{$db_username}'
if($username == "{$db_username}") // will be true because 'admin' == 'admin'
if($username == $db_username) // same as before but cleaner (and a little bit faster, maybe?)
?>
I did ask whether or not usernames were unique in the db - if they are then there would be no need for a loop and using a loop would mean that on the first iteration into the recordset the logic tests ( that were failing anyway ) would run and the redirection would occur without any further processing.
Perhaps the following might help.
<?php
if( isset( $_POST['login'], $_POST['username'], $_POST['password'] ) ) {
include 'db.php';
/*
Using prepared statements means you don't need to try to sanitize user input data prior
to executing the sql query in an attempt to prevent sql injection.
*/
$username = $_POST['username'];
$password = $_POST['password'];
/*
The original query returned many fields which were never used. When using `prepared statements` and binding
the results you need to specify a binding for all fields returned - hence returning only two fields.
*/
$query = "SELECT `username`,`password`,`role` FROM `tbl_users` WHERE `username` = ? ";
$stmt = $connection->prepare( $query );
if( $stmt ){
$stmt->bind_param( 's', $username );
$stmt->execute();
$stmt->store_result();
/* Capture db results into variables to use in logic test below */
$stmt->bind_result( $dbusername, $dbpassword, $dbrole );
$stmt->fetch();
$stmt->close();
$connection->close();
/* possible endpoints for redirection */
$redirect = 'login.php';
if( $username == $dbusername && $password == $dbpassword ) {
/* What values are held in `role` field? assumed "admin" */
$redirect = $dbrole == 'admin' ? 'admin' : 'index.php';
}
exit( header( "Location: ../{$redirect}" ) );
}
}
?>
A login generally need a session to store informations about your status.
So, first thing to do is initialize the sessions, put this code at top of the page, before all:
session_start();
After this, a few considerations must be done:
I'll expect that the field username is unique: put a unique index on your db on this field to ensure the unicity
Change your query, putting the password check inside it
Fetch only one row, without using a while: if the username is unique you will get only one row. The password can be checked inside query as said before, so if query dest not return rows, user is not registered or credentials are wrong.
If you get results, then you can check the role and redirect to the right page.
If you can authenticate the user, set a session like:
$_SESSION['user'] = array(
'is_logged' => $user_id,
'username' => $username,
'role' => $role,
'email' => $email,
);
Every time you load a page, check if(empty($session['user']['is_logged'])) { .... }. If true, the user is not logged.
Don't save user password as plain text, but hash it! You can use MySQL PASSWORD() function.
$username !== '{$db_username}' && $password !== '{$db_password}'
This code will not work, and probably is the main problem, single quotes are not parsed by PHP, use $username == $db_username && $password == $db_password instead (if you do this check inside the query, this code is not neeeded anymore)
I keep getting the following error Undefined variable: password on line 33 how do I correct this problem? So this error will stop showing.
Here is the php code.
$first_name = mysqli_real_escape_string($mysqli, $purifier->purify(htmlentities(strip_tags($_POST['first_name']))));
$password1 = mysqli_real_escape_string($mysqli, $purifier->purify(strip_tags($_POST['password1'])));
$password2 = mysqli_real_escape_string($mysqli, $purifier->purify(strip_tags($_POST['password2'])));
// Check for a password and match against the confirmed password:
if ($password1 == $password2) {
$sha512 = hash('sha512', $password1);
$password = mysqli_real_escape_string($mysqli, $sha512);
} else {
echo '<p class="error">Your password did not match the confirmed password!</p>';
}
//If the table is not found add it to the database
if (mysqli_num_rows($dbc) == 0) {
$mysqli = mysqli_connect("localhost", "root", "", "sitename");
$dbc = mysqli_query($mysqli,"INSERT INTO users (user_id, first_name, password)
VALUES ('$user_id', '$first_name', '$password')");
}
//If the table is in the database update each field when needed
if ($dbc == TRUE) {
$dbc = mysqli_query($mysqli,"UPDATE users
SET first_name = '$first_name', password = '$password'
WHERE user_id = '$user_id'");
echo '<p class="changes-saved">Your changes have been saved!</p>';
}
There's only one place where a value is assigned to $password
if ($password1 == $password2) {
$sha512 = hash('sha512', $password1);
$password = mysqli_real_escape_string($mysqli, $sha512);
}
So, if the condition isn't met there will be no $password. And in that case it doesn't make sense to perform the UPDATE query anyway.
At the top define
$password = '';
then change the DBC check to
if ($dbc == TRUE && $password != ''){
As you can see, the database insert is done whether the first if() was true or false. If it's false ($password1 and $password2 doesn't match), $password won't be defined.
If this condition fails:
if ($password1 == $password2) {
$password will not get defined, raising an error in one of the lines it is used in later.
You don't raise an ERROR with an ELSE statement on the $password = ...... line so there is clearly an error there and it's not being defined. The top level if statement is fine, but the error is on the $password declaration line. Do you see how that works?
Instead of retrying the query if the insert fails (presumably because the user_id already exists - you've made that your primary key?), you could use the alternate INSERT INTO ... ON DUPLICATE KEY UPDATE syntax:
INSERT INTO users (user_id, first_name, password)
VALUES ('$user_id', '$first_name', '$password')
ON DUPLICATE KEY UPDATE
first_name=VALUES(first_name),
password=VALUES(password)
On a nitpicky point, your comments say "if the table is not found" and "if the table...". You're not dealing with table creation/modification - you're working with records that are stored in a table.