Getting an error using mysqli_escape_string functi

2019-09-17 20:49发布

问题:

I get an error on the last line on mysqli_escape_string($hash)); by using the following code:

$hash = md5( rand(0,1000) );
$stmt = $mysqli->prepare("INSERT INTO users (username, password, hash) VALUES (?, ?, mysqli_escape_string($hash))");
$password = md5($password);
$stmt->bind_param('ss', $username, $password, mysqli_escape_string($hash));

It says, that the mysqli_escape_string($hash)) is a non-object. But using only $hash instead doesn't help either

Can someone help?

回答1:

There are far too many things wrong with your code and will be extremely difficult to provide a solution by fixing what you have now.

Firstly, MD5 is no longer considered safe to use for password storage.

Consult:

  • https://security.stackexchange.com/questions/19906/is-md5-considered-insecure
  • https://en.wikipedia.org/wiki/MD5

Plus, you're not using prepared statements correctly.

  • Consult: http://php.net/manual/en/mysqli.prepare.php

As I stated, the mysqli_escape_string() function requires a database connection be passed as the first parameter:

  • http://php.net/manual/en/mysqli.real-escape-string.php

Do yourself a favor and use this, one of ircmaxell's answers https://stackoverflow.com/a/29778421/

Pulled from his answer:

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
}


回答2:

Your code should be

$hash = md5( rand(0,1000) );
$stmt = $mysqli->prepare("INSERT INTO users (username, password, hash) VALUES (?, ?, ?)");
$password = md5($password);
$stmt->bind_param('sss', $username, $password, $hash);

You don't need to escape with parameterized queries.

Issues you had, your escape function was incorrect you need the object with the function when using OO approach.

$mysqli->real_escape_string($hash);

would have been what you wanted.

You also were binding that value again though which would have thrown an error and didn't set it in the variable types being passed.

A string that contains one or more characters which specify the types for the corresponding bind variables.

So

$stmt->bind_param('ss', $username, $password, mysqli_escape_string($hash));

should have had three 's's because there are three strings, and no need for the escaping.

Also md5ing passwords isn't the best practice anymore, take a look at:

Secure hash and salt for PHP passwords

https://security.stackexchange.com/questions/19906/is-md5-considered-insecure