Plenty of time, spent, here is where I'm at:
$uname_query = mysql_query("SELECT username FROM blog_members WHERE username='".$username."'");
if ($uname_query == $username) {
$error[] = 'Username is already taken';
}
I'm trying to use the SQL query $uname_query to pull the $username entered in a form, if it exists, then use an if statement to display the error, if it exists.
As it is coded right now, I get no error but also no functionality.
What am I missing?
You need to use a fetch.
$row = mysql_fetch_row($uname_query);
// $row[0] will contain the first column of the first row (username)
if ($row[0] == $username) { }
However, you should look at using PDO or MySQLi since the MySQL api is deprecated. You should also use prepared statements if $username is provided by the user.
In PDO you could do:
$stmt = $pdo->prepare("SELECT username FROM blog_members WHERE username=?");
$stmt->execute(array($username));
// fetchColumn will return the first column of the first row (username)
if ($stmt->fetchColumn() == $username) { }
This protects against SQL injections by providing a prepared statement without $username and binding it in the execute() function. PDO requires some different setup initially too, but here is a good tutorial: http://wiki.hashphp.org/PDO_Tutorial_for_MySQL_Developers
You have to fetch the data before compare as
$row = mysql_fetch_array( $uname_query);
if($row["username"] == $username){
$error[] = 'Username is already taken';
}
You need to fetch the data from the query first.
$uname_query = mysql_query("SELECT username FROM blog_members WHERE username='".$username."'");
$arr=mysql_fetch_array($uname_query);
if ($arr["username"] == $username) {
$error[] = 'Username is already taken';
}
For one, you need to fetch it. Use mysql_fetch_row(). Secondly, I'm not sure what that $error[]='string' business is. Are you trying to use an array?
Although I suggest moving to mysqli since mysql is deprecated. Also, I hope you sanitized that string well.
Related
I have a PHP script using PDO where I check a user's submitted email/password against a database. If the query returns a row, it is supposed to take the user to a success page, or if the credentials are incorrect they are supposed to be taken to a failed login page. However, the user is always taken to the fail page.
$sql = "SELECT email, password FROM user WHERE email= $email AND password = $password";
$stm = $db->prepare($sql);
$stm->execute();
$result = $stm->fetchColumn();
if ($result !== FALSE) {
header('Location: ./success.html');
}
else {
header('Location: ./failed.html');
}
Your original problem was simply missing quotes around the variables inserted into the query.
Just fixing that problem would leave you vulnerable to SQL injection attacks. Making proper use of statement preparation and execution will solve that problem. And never, never, store plaintext passwords. When you save them, use password_hash and then use code like this to verify them.
$password = $_POST["password"];
$email = $_POST["email"];
$sql = "SELECT password FROM user WHERE email= ?";
$stm = $db->prepare($sql);
$stm->execute([$email]);
$result = $stm->fetchColumn();
if ($result !== FALSE) {
if (password_verify($password, $result[0])) {
header("Location: ./success.html);
exit;
}
}
header("Location: ./failed.html");
More details on password hashing can be found elsewhere on SO.
And please note that for brevity I'm not checking the result of the prepare() or execute() functions. You should be doing this.
This question already has answers here:
How can I prevent SQL injection in PHP?
(27 answers)
Can I mix MySQL APIs in PHP?
(4 answers)
Closed 3 years ago.
I am very new to mysqli earlier i am writing queries in mysql but mysqli is more advanced so, i am first time using it.
Below is my php code.
function clean($str) {
$str = #trim($str);
if(get_magic_quotes_gpc()) {
$str = stripslashes($str);
}
return mysql_real_escape_string($str);
}
$email = clean($_POST['email']);
$password = clean($_POST['password']);
//$password =md5($password);
if(empty($res['errors'])) {
$result = $mysqli->query("SELECT uid FROM users where email='$email' and password = '$password'");
if($result->num_rows == 1){
$res['success'] = true;
}
else{
array_push($res['errors'], 'Invalid login details');
$res['success'] = false;
}
}else{
$res['success'] = false;
}
echo json_encode($res);
}
clean function is not working as expected because sql queries return false if i enter username and password correct.
So, it seems like this is not valid in mysqli case.
I checked this link PHP MySQLI Prevent SQL Injection and got to know that we have to prepare query.
I can see there is an example but i am not able to understand how to prepare/bind if i have to use two or more form data.
Thanks for your time.
Updated code
$result = $mysqli->prepare("SELECT uid FROM users where email=:email and password = :password");
$result->execute([
':email' => $email,
':password' => $password]);
//$result->execute();
if($result->num_rows == 1){
//if(mysqli_num_rows($result) === 1) {
$res['success'] = true;
}
else{
array_push($res['errors'], 'Invalid login details');
$res['success'] = false;
}
As already stated in comments, you need to be consistent with your API choice. You can't mix APIs in PHP.
You started out with mysqli_*, so I'll continue with that. You had some mysql_* and PDO in there, and it might not be a bad idea to use PDO over mysqli_* - but if your server supports mysqli_*, there is nothing wrong with using that. See Choosing an API and decide for yourself (just stay away from mysql_*, it's outdated).
Using mysqli_*, you connect to the database like this (you didn't show your connection).
$mysqli = new mysqli("host", "username", "password", "database");
if ($mysqli->connect_errno) {
echo "Failed to connect to MySQL: (".$mysqli->connect_errno.") ".$mysqli->connect_error;
}
$mysqli->set_charset("utf8");
As for preventing SQL injection in it self, all you need is to use prepared statements. You can still clean or sanitize your data if there are some kind of values you don't want sitting in your tables - but that's kind of another discussion.
You also need to know if your passwords are hashed in the database. They really should be, and you should be using password_hash($password, $algorithm) and password_verify($password, $hash) if you're on PHP5.5 and above (if not, look into something like password_compat).
You need to be consistent with your hashes too, you can't insert it with md5 and selecting it with no hash. It all needs to be the same. Because if you are selecting an md5 hash, and comparing it to an unhashed string, they will be different, and the query fails.
I'm showing you an example of using password_verify(), so that means that the password stored in the database will also need to be stored with password_hash() (or your query fails).
if ($stmt = $mysqli->prepare("SELECT uid, password FROM users where email=?")) {
$stmt->bind_param("s", $_POST['email']); // Bind variable to the placeholder
$stmt->execute(); // Execute query
$stmt->bind_result($userID, $password); // Set the selected columns into the variables
$stmt->fetch(); // ...and fetch it
if ($stmt->num_rows) {
if (password_verify($_POST['password'], $password)) {
// Password was correct and matched the email!
} else {
// Password was incorrect...
}
} else {
// Accountname not found
}
}
This is just a basic example, but it will get you started. Never trust user input, use prepared statements.
You can bind more variables like so:
$stmt = $mysqli->prepare("SELECT uid FROM users where email= ? and password = ?");
$stmt->bind_param('ss', $email, $password);
/* execute prepared statement */
$stmt->execute();
As you can see, you can expand on the bind_param() function. You can also add different type of variables:
i corresponding variable has type integer
d corresponding variable has type double
s corresponding variable has type string
b corresponding variable is a blob and will be sent in packets
From: http://php.net/manual/en/mysqli-stmt.bind-param.php
First of all, I suggest you learn PDO instead of MySQLi, just because it supports more drivers.
Second, you use mysql_real_escape_string, as you might see, that is a MySQL function, not a MySQLi function.
So where you have:
$result = $mysqli->query("SELECT uid FROM users where email='$email' and password = '$password'");
You should do something like:
<?php
$stmt = $dbConnection->prepare("SELECT uid FROM users where email = :email AND password = :password");
try{
$stmt->execute([
':email' => $email,
':password' => $password
]);
}
catch(Exception $e){
echo $e->getMessage(); //Remove when putting online
}
if($stmt->num_rows){
$res['success'] = true;
}
?>
You're presently mixing MySQL APIs/functions with mysql_real_escape_string(), then num_rows and then a PDO binding method where email=:email and password = :password which seems to have been taken from another answer given for your question.
Those different functions do NOT intermix.
You must use the same one from connection to querying.
Consult: Can I mix MySQL APIs in PHP?
It looks like you're wanting to setup a login script. I suggest you use the following and pulled from one of ircmaxell's answers:
Pulled from https://stackoverflow.com/a/29778421/
Just use a library. Seriously. They exist for a reason.
PHP 5.5+: use password_hash()
PHP 5.3.7+: use password-compat (a compatibility pack for above)
All others: use phpass
Don't do it yourself. If you're creating your own salt, YOU'RE DOING IT WRONG. You should be using a library that handles that for you.
$dbh = new PDO(...);
$username = $_POST["username"];
$email = $_POST["email"];
$password = $_POST["password"];
$hash = password_hash($password, PASSWORD_DEFAULT);
$stmt = $dbh->prepare("insert into users set username=?, email=?, password=?");
$stmt->execute([$username, $email, $hash]);
And on login:
$sql = "SELECT * FROM users WHERE username = ?";
$stmt = $dbh->prepare($sql);
$result = $stmt->execute([$_POST['username']]);
$users = $result->fetchAll();
if (isset($users[0]) {
if (password_verify($_POST['password'], $users[0]->password) {
// valid login
} else {
// invalid password
}
} else {
// invalid username
}
It's safer and uses a safe password hashing method, rather than what you seem to want to use is MD5 $password =md5($password); and is no longer considered safe to use now.
References:
PDO connection http://php.net/manual/en/pdo.connections.php
PDO error handling http://php.net/manual/en/pdo.error-handling.php
To check if a user exists, you can see one of my answers https://stackoverflow.com/a/22253579/1415724
http://php.net/manual/en/mysqli.error.php
http://php.net/manual/en/function.error-reporting.php
Sidenote: If you do go that route, remember to read the manuals and that your password column is long enough to hold the hash. Minimum length is 60, but they recommend 255.
It is also unclear if your HTML form does have name attributes for the POST arrays, so make sure the form is using a POST method.
http://php.net/manual/en/tutorial.forms.php
I believe I have given you enough information to get started.
What you must NOT do, is to use the above with your present code and simply patching it. You need to start over.
Add error reporting to the top of your file(s) which will help find errors.
<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);
// rest of your code
Sidenote: Displaying errors should only be done in staging, and never production.
I'm trying to create a login system with PHP, but the SQL query is not returning the result I'm expecting.
I have a typical username and password page, and I'm using what the user types in there to check for an account. I know for a fact that the database contains real usernames and passwords but the call to mysqli_num_rows is always returning 0.
Is there something I'm doing wrong?
$username = $_POST['username'];
$password = $_POST['password'];
$result = mysqli_query($con, "SELECT * FROM StaffTable WHERE staffNo='$username' AND password='$password'");
echo mysqli_num_rows($result); //This always prints out 0.
if(mysqli_num_rows($result) == 1)
{
echo "OK";
}
Ignoring the plain-text-password thing which you claim to be aware of, something like this perhaps...
$username = isset($_POST['username']) ? $_POST['username'] : null;
$password = isset($_POST['password']) ? $_POST['password'] : null;
$stmt = $con->prepare('SELECT 1 FROM StaffTable WHERE staffNo = ? AND password = ?');
if (!$stmt) {
throw new Exception($con->error, $con->errno);
}
$stmt->bind_param('ss', $username, $password);
if (!$stmt->execute()) {
throw new Exception($stmt->error, $stmt->errno);
}
if ($stmt->fetch()) {
echo 'OK';
}
To summarise...
I've checked that the input variables are set and assigned defaults if they're not that shouldn't produce any false positives
I've used a prepared statement with bound parameters to avoid SQL injection vulnerabilities
I throw exceptions when errors occur. These are great because they halt execution and give you all the information you need to debug the problem.
This is my main problem with mysqli over PDO. mysqli is simply not noisy enough when errors occur. You shouldn't have to manually check for error conditions all the time.
I've changed the query to a simple boolean check as that's all you were using it for. The row either exists, or it doesn't.
Try something more along the lines of
$username=$_POST['username'];
$password=md5($_POST['password']);
$query="SELECT * FROM StaffTable WHERE staffNo='".$username."' AND password='".$password."'";
$result=mysqli_query($con,$query);
if (mysqli_num_rows($result)==0)
{
echo "Incorrect Password Or Username Combo";
}
else {
while($row=mysqli_fetch_object($result)) {
$_SESSION['id']=$row['id'];
}
I would say to start with at least running the passwords in encryption for now and look into SQL injection and upgrade as you learn more about what you're looking at.
The biggest flaw in yours aside from what's already been pointed out is
($con, "SELECT * FROM StaffTable WHERE staffNo='$username' AND password='$password'");
With the variables you cannot put them within the query that way; you would want to do something more along the lines of
($con, "SELECT * FROM StaffTable WHERE staffNo='".$username."' AND password='".$password."'");
If you'll notice I escaped from the plain text so that the variables would be set. The reason you're returning 0 results everytime is because you are actually searching for username $username with $password as their password.
Good luck!
This register form was made by me, but it doesn't do what I want it to do.
I want it to connect to a mysql database and store the information that was given by the form. I want it to hash the $password in md5 and store it in the "gebruikers" table. Please don't reply with "Damn, you have no idea what you are doing" or something like that. I am learning PHP by looking to examples and following tutorials. Please keep in mind that the mysql insert code is not filled in right, because I got stuck a few lines above.
So, my question is: I want to check if the mysql table already contains $email. If it IS already in the mysql table, I want to display an error message that I can place somewhere else in my PHP page. If the email adress given is unique, than the $password should hash into md5 and store into the mysql database, just like the other form entries.
How do I do that?
<?php
// Fetching all the form details
$email = $_POST["email"];
$password = $_POST["password"];
$voornaam = $_POST["voornaam"];
$tussenvoegsel = $_POST["tussenvoegsel"];
$achternaam = $_POST["achternaam"];
$dag = $_POST["dag"];
$maand = $_POST["maand"];
$jaar = $_POST["voornaam"];
$straat = $_POST["straat"];
$postcode = $_POST["postcode"];
$woonplaats = $_POST["woonplaats"];
$cniveau = $_POST["cniveau"];
$oniveau = $_POST["oniveau"];
$voornaam = $_POST["voornaam"];
$aboutme = $_POST["aboutme"];
//Here's where I don't know how to continue
$check = mysql_query("SELECT * FROM `gebruikers` WHERE `email` = '$email'");
if($check === FALSE) {
//there is a user already registered
echo("$email is al in gebruik. <a href='login.php'>Inloggen</a>?");
} else {
//There isn't a username
//mysql_query("INSERT INTO `user` (`id` ,`username` ,`password`) VALUES (NULL , '{$_POST['email']}', MD5( '{$_POST['password']}' ))");
echo("You have been registered!");
}
P.S.: I'm not a native English speaker, so please ignore my grammar mistakes/typos.
First of all, you made a major mistake: There is a SQL-Injection security hole.
Please read this: http://php.net/manual/en/security.database.sql-injection.php
Second, you should use mysqli instead of mysql, because mysql is deprecated.
Your error is that SQL does only return false if the query is invalid, not if there are no results. So the correct way of checking if there are results is to use http://php.net/manual/en/mysqli-result.num-rows.php
$result = mysql_query("SELECT * FROM `gebruikers` WHERE `email` = '$email' LIMIT 1");
if(mysql_fetch_array($result) !== false)
{
...
} else {
....
}
You should also read up on preventing SQL injection.
Maybe you've forgot to set the mysql_connect statement.
But I strongly recommend you stick from now on, with the mysqli_ functionality, since, as Aragon0 said, mysql is deprecated in PHP's newest versions.
Besides, mysqli statements are simpler than the mysql ones, for example you use one statement (mysqli_connect) to connect to your host and select your database at the same time, instead of using separated statements (both mysql_connect and mysql_select_db).
Oh, and no additional service package is required to use it. :)
Hello every one i'm trying to do a login method for my website, and i'm having a small problem. I'm getting the data from PDO connection but every time im checking the password it returns false. is my variables wrong?
here is my sql query
$this->result = $this->sql->prepare('SELECT username,password FROM User WHERE username=:username AND password=:password');
$this->result->bindParam(':username', $username, PDO::PARAM_STR);
$this->result->bindParam(':password', $password, PDO::PARAM_STR);
$this->result->execute();
and here is my if statement:
$this->result=$this->result->fetch(PDO::FETCH_OBJ);
if (($password == $this->result->password) && ($username == $this->result->username)){
i'm not getting error it just return always false. i'm not encrypting the password yet so is not this problem. i think $this->result->password is the problem. can anyone correct me please?
thank you
You can use this as well:
$username=$_GET['username'];$password = $_GET['password'];/*of $_POST, depending of which you used*/
$this->result = $this->sql->prepare('SELECT username,password FROM User WHERE username='$username' AND password='$password');
$this->result->execute();
And then use fetchAll like this:
$this->results = $this->result->fetchAll(PDO::FETCH_ASSOC);
if($this->results['username']==$this->username && $this->results['password']==$this->password){/*u had beed loged in*/}
Your logic should work. Most likely, the SQL is not returning anything. Try printing out the result of your fetch.
$this->result=$this->result->fetch(PDO::FETCH_OBJ);
print_r($this->result);
Also, if you are checking for username and password in the SQL query, you don't have to check it again in the if statement. With the SQL statement you are using, you should be able to just check if it returned a row or not to validate the user.
$numrows = $this->result->rowCount();
if ($numrows == 1) {
// User is valid
}
else {
// User is not valid
}