我在将password_hash存储到MySql数据库时遇到了问题。它从一开始就切断了角色,而在两者之间切断了角色。
我已尝试在HTML中将编码设置为UTF 8,在connect函数中设置相同,并且我已将排序规则更改为每种可能的类型。然而,我能够将回声中的正确哈希粘贴到数据库中,并且工作正常。
$password = $_POST['pno'];
$pno = password_hash($password,PASSWORD_DEFAULT);
MySqlDb::query('INSERT INTO user (name, email, pno, address_line_1, address_line_2, town, county, post_code, phone) VALUES (:name, :email, :pno, :address_line_1, :address_line_2, :town, :county, :post_code, :phone)',
[':name'=>$name, ':email'=>$email, ':pno'=>$pno, ':address_line_1'=>$address_line_1, ':address_line_2'=>$address_line_2, ':town'=>$town, ':county'=>$county, ':post_code'=>$post_code, ':phone'=>$phone]);
echo $pno;
所以回声会给我这个:$ 2y $ 10 $ rtlUaDeXsyhtWS5.SS4nuu.xapBdrHXG7V.DpSLCLAAwYqXPJHKWi
但是在数据库中它存储了这个: Y $ rtlUaDeXsyhtWS5.SS4nuu.xapBdrHXG7V.DpSLCLAAwYqXPJHKWi
我也尝试过编码和解码功能,几乎都是出于创意。
class MySqlDb {
/**
* @var MySQLi instance
*/
protected static $link;
/**
* @var bool set to true to print query before executing
*/
public static $debug = false;
/**
* Creates a new MySQLi instance use getConnection() to retrieve
* @return none
*/
private function __construct() {
self::$link = @mysqli_connect(DATABASE_HOST, DATABASE_USERNAME, DATABASE_PASSWORD, DATABASE_NAME);
if (mysqli_connect_errno()) {
//die('MySqlDb Error: Could not connect to database ('.mysqli_connect_errno().')');
throw new Exception('MySqlDb::() Could not connect to database (' . mysqli_connect_errno() . ')');
}
}
/**
* Returns the MySQLi connection
* @return MySQLi instance
*/
public static function getConnection() {
if (!self::$link) {
new MySqlDb();
}
return self::$link;
}
/**
* Helper function for mysqli_query if params are given will use quote function
* see below MySqlDb:quote this is to help avoid sql injection attacks and automatically escape slashes etc
*
* @param string $sql
* @param array $params
* @return mysqli_query resource ...
*
* Example:
* MySqlDb::query("drop from user where id=$_GET['id']"); // very bad 'id' could contain "' or 1=1"
* MySqlDb::query("drop from user where id=:id", [':id' => $_GET['id']]); // much better
*/
public static function query($sql, array $params = null) {
$con = self::getConnection();
if (!empty($params)) {
$sql = self::quote($sql, $params);
}
if (self::$debug) {
echo $sql;
}
$res = mysqli_query($con, $sql);
if (!$res) {
//die('MySqlDb Error: query: '.mysqli_error($con));
throw new Exception('MySqlDb::query() ' . mysqli_error($con));
}
return $res;
}
/**
* Helper function to quote sql values similar to pdo::bindvalue using named parameters
* to help avoid sql injection attacks and avoid using stuff like addslashes
*
* @param string $sql sql string to quote
* @param array $params key value pairs of parameters and values to placed into them
* @return string sql quoted string
*
* Example:
* $sql = MySqlDb::quote("select * from users where id=:unique1 or id=:unique2", [':unique1'=>2, ':unique2'=>4])
* TODO:
* MySqlDb::quote("select * from users where id+5 = :id or id = :id",[':id'=>3] fails on number params dont match like pdo
* could convert 'substr_count($sql, ':')' into '$unique_sql_param_count'
* e.g. preg_match_all("/:[\w-_]+\b/i", $test, $matches); $paramcount = count(array_flip($matches[0]));
*/
public static function quote($sql, array $params) {
// check correct number of params
if (substr_count($sql, ':') != count($params)) {
//die('MySqlDb Error: quote: number params do not match');
throw new Exception('MySqlDb::quote() number params do not match');
}
$cnt = 0;
foreach ($params as $param => $value) {
//$sql = str_replace($param, "'".self::escape($value)."'", $sql, $cnt); // was matching sub strings :(
$sql = preg_replace("/$param\b/i", "'" . self::escape($value) . "'", $sql, -1, $cnt);
if ($cnt !== 1) {
//die("MySqlDb Error: quote: param '{$param}' not matched or is duplicate");
throw new Exception("MySqlDb::quote() param '{$param}' not matched or is duplicate");
}
}
return $sql;
}
/**
* Wrapper for mysqli_escape_string
* @param mixed $value
* @return escaped value
*/
public static function escape($value) {
return mysqli_escape_string(self::getConnection(), $value);
}
/**
* Helper function to return all rows in result as an associative array
* @param string $sql
* @return array array of arrays
*/
public static function all($sql, array $params = null) {
return mysqli_fetch_all(self::query($sql, $params), MYSQLI_ASSOC);
}
/**
* Helper function to return first row in result from potential multiple values
* @param string $sql
* @return array single array
*/
public static function first($sql, array $params = null) {
$res = mysqli_fetch_array(self::query($sql, $params), MYSQLI_ASSOC);
return is_array($res) ? $res : [];
}
/**
* Helper function to return first field in result from potential multiple values
* @param string $sql
* @return mixed single variable
*/
public static function scalar($sql, array $params = null) {
$res = mysqli_fetch_array(self::query($sql, $params), MYSQLI_NUM);
return is_array($res) ? $res[0] : null;
}
}
答案 0 :(得分:2)
quote
方法中的这一行是问题的直接原因。
$sql = preg_replace("/$param\b/i", "'" . self::escape($value) . "'", $sql, -1, $cnt);
self::escape($value)
的结果将是您原来的哈希值,
$2y$10$rtlUaDeXsyhtWS5.SS4nuu.xapBdrHXG7V.DpSLCLAAwYqXPJHKWi
在preg_replace
的上下文中,$2
和$10
是有意义的。在the Parameters section of the preg_replace
documentation中,它说
替换可能包含\ n或$ n形式的引用,后一种形式是首选形式。每个这样的引用都将被第n个括号模式捕获的文本替换。
您没有带括号的模式,因此这些值将被替换为任何内容。
您可以通过转义替换参数中的任何$
来修复它,但我宁愿建议使用创建预准备语句并绑定参数的方法替换基于转义/替换的quote
方法在执行之前。