password_hash进入MySQL数据库切断/切出字符

时间:2018-04-06 15:34:22

标签: php mysql php-password-hash

我在将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;
    }

}

1 个答案:

答案 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方法在执行之前。