• 企业400电话
  • 微网小程序
  • AI电话机器人
  • 电商代运营
  • 全 部 栏 目

    企业400电话 网络优化推广 AI电话机器人 呼叫中心 网站建设 商标✡知产 微网小程序 电商运营 彩铃•短信 增值拓展业务
    PHP中常见的密码处理方式和建议总结

    前言

    在使用PHP开发Web应用的中,很多的应用都会要求用户注册,而注册的时候就需要我们对用户的信息进行处理了,最常见的莫过于就是邮箱和密码了,本文意在讨论对密码的处理:也就是对密码的加密处理。

    密码安全的重要性我们就不用再去强调,随着在线攻击的增多,如果我们对密码没有进行合适的处理或做防御措施,我们的应用就会肯定会收到来自各方的威胁和攻击。

    所以作为开发者,我们需要对用户的密码做好预防措施。

    关于密码我们应该遵守的一些原则

    绝对不能知道用户的密码

    绝对不去约束用户的密码

    绝对不通过电子邮件发送用户的密码

    对于一个web应用来说,重置或修改密码时,我们应该在邮件里发送用于设定或修改密码的 URL 。而且这个URL中应该会包含一个唯一的令牌,这个令牌只能在设定或修改密码时使用一次。在设定或修改密码之后,我们就应该把这个令牌置为失效。

    使用 bcrypt 计算用户密码的哈希值

    目前,通过大量的审查,最安全的哈希算法是 bcrypt 。

    首先,我们明确两个概念,哈希、加密。哈希和加密有什么区别?

    加密

    加密是双向算法,加密的数据之后通过解密还可以得到。

    哈希

    哈希是单向算法,哈希后的数据不能再还原成原始值。

    哈希算法的用途,

    验证数据的完整性(要求算法速度快)

    哈希的算法有很多种,

    MD5

    MD5即Message-Digest Algorithm 5(信息-摘要算法5),用于确保信息传输完整一致。是计算机广泛使用的杂凑算法之一(又译摘要算法、哈希算法),主流编程语言普遍已有MD5实现。将数据(如汉字)运算为另一固定长度值,是杂凑算法的基础原理,MD5的前身有MD2、MD3和MD4。

    SHA1

    安全哈希算法(Secure Hash Algorithm)主要适用于数字签名标准 (Digital Signature Standard DSS)里面定义的数字签名算法(Digital Signature Algorithm DSA)。对于长度小于2^64位的消息,SHA1会产生一个160位的消息摘要。当接收到消息的时候,这个消息摘要可以用来验证数据的完整性。在传输的过程中,数据很可能会发生变化,那么这时候就会产生不同的消息摘要。 SHA1有如下特性:不可以从消息摘要中复原信息;两个不同的消息不会产生同样的消息摘要,(但会有1x10 ^ 48分之一的机率出现相同的消息摘要,一般使用时忽略)。

    bcrypt

    bcrypt是专门为密码存储而设计的算法,基于Blowfish加密算法变形而来,由Niels Provos和David Mazières发表于1999年的USENIX。 bcrypt最大的好处是有一个参数(work factor),可用于调整计算强度,而且work factor是包括在输出的摘要中的。随着攻击者计算能力的提高,使用者可以逐步增大work factor,而且不会影响已有用户的登陆。 bcrypt经过了很多安全专家的仔细分析,使用在以安全著称的OpenBSD中,一般认为它比PBKDF2更能承受随着计算能力加强而带来的风险。bcrypt也有广泛的函数库支持,因此我们建议使用这种方式存储密码。

    scrypt

    scrypt不仅计算所需时间长,而且占用的内存也多,使得并行计算多个摘要异常困难,因此利用rainbow table进行暴力攻击更加困难。scrypt没有在生产环境中大规模应用,并且缺乏仔细的审察和广泛的函数库支持 。但是,scrypt在算法层面只要没有破绽,它的安全性应该高于PBKDF2和bcrypt。

    目前,通过大量的审查,最安全的哈希算法是 bcrypt 。与 MD5 和 SHA1 不同, bcrypt 算法会自动加盐,来防止潜在的彩虹表攻击。 bcrypt 算法会花费大量的时间反复处理数据,来生成安全的哈希值。在这个过程中,处理数据的次数叫工作因子(work factor)。工作因子的值越高,破解密码哈希值的时间会成指数倍增长。

    bcrypt 算法永不过时,如果计算机的运算速度变快了,我们只需要提高工作因子即可。

    顺带说一下,任何情况下尽可能的不要使用 md5 算法,至少也要使用 SHA 系列的哈希算法。因为md5算法以目前计算机的计算能力来说显得比较简单,而 md5 的性能优势现在也已经完全可以忽略不计了。

    密码哈希API

    上面我们说到 bcrypt 算法最安全,最适合对我们的密码进行哈希。 PHP 在 PHP5.5.0+ 的版本中提供了原生的密码哈希API供我们使用,这个密码哈希API默认使用的就是 bcrypt 哈希算法,从而大大简化了我们计算密码哈希值和验证密码的操作。

    PHP原生密码哈希API

    密码哈希函数:

    password_get_info

    说明

    array password_get_info ( string $hash )

    参数

    hash, 一个由 password_hash() 创建的散列值。

    示例,

    ?php
    var_dump(password_get_info($hash));
    // Example
    array(3) {
     ["algo"]=>
     int(1)
     ["algoName"]=>
     string(6) "bcrypt"
     ["options"]=>
     array(1) {
     ["cost"]=>
     int(10)
     }
    }
    ?>

    password_hash

    说明

    string password_hash ( string $password , integer $algo [, array $options ] )

    password_hash() 使用足够强度的单向散列算法创建密码的哈希(hash)。 password_hash() 兼容 crypt()。 所以, crypt() 创建的密码哈希也可用于 password_hash()。

    当前支持的算法:

    支持的选项:

    参数

    示例

    示例1,使用默认算法哈希密码

    ?php
    /**
     * 我们想要使用默认算法哈希密码
     * 当前是 BCRYPT,并会产生 60 个字符的结果。
     *
     * 请注意,随时间推移,默认算法可能会有变化,
     * 所以需要储存的空间能够超过 60 字(255字不错)
     */
    echo password_hash("rasmuslerdorf", PASSWORD_DEFAULT)."\n";
    ?>
    // 输出类似于:
    // $2y$10$.vGA1O9wmRjrwAVXD98HNOgsNpDczlqm3Jq7KnEd1rVAGv3Fykk1a

    示例2,手动设置 cost

    ?php
    /**
     * 在这个案例里,我们为 BCRYPT 增加 cost 到 12。
     * 注意,我们已经切换到了,将始终产生 60 个字符。
     */
    $options = [
     'cost' => 12,
    ];
    echo password_hash("rasmuslerdorf", PASSWORD_BCRYPT, $options)."\n";
    ?>
    // 输出类似于:
    // $2y$12$QjSH496pcT5CEbzjD/vtVeH03tfHKFy36d4J0Ltp3lRtee9HDxY3K

    示例3,如何选择一个适合当前服务器的 cost

    ?php
    /**
     * 这个例子对服务器做了基准测试(benchmark),检测服务器能承受多高的 cost
     * 在不明显拖慢服务器的情况下可以设置最高的值
     * 8-10 是个不错的底线,在服务器够快的情况下,越高越好。
     * 以下代码目标为 ≤ 50 毫秒(milliseconds),
     * 适合系统处理交互登录。
     */
    $timeTarget = 0.05; // 50 毫秒(milliseconds)
    
    $cost = 8;
    do {
     $cost++;
     $start = microtime(true);
     password_hash("test", PASSWORD_BCRYPT, ["cost" => $cost]);
     $end = microtime(true);
    } while (($end - $start)  $timeTarget);
    
    echo "Appropriate Cost Found: " . $cost . "\n";
    ?>

    输出类似于:

    Appropriate Cost Found: 10

    password_needs_rehash

    说明

    boolean password_needs_rehash ( string $hash , integer $algo [, array $options ] )

    参数

    示例,

    ?php
    $password = 'rasmuslerdorf';
    $hash = '$2y$10$YCFsG6elYca568hBi2pZ0.3LDL5wjgxct1N8w/oLR/jfHsiQwCqTS';
    
    // cost 参数可随硬件的提升也不断提升
    $options = array('cost' => 11);
    
    // 使用纯文本密码 验证存储的散列
    if (password_verify($password, $hash)) {
     // 检查是否有更新的散列算法可用或 cost 是否已经改变
     if (password_needs_rehash($hash, PASSWORD_DEFAULT, $options)) {
      // 如果是,请创建一个新的哈希值,并替换旧的哈希值
      $newHash = password_hash($password, PASSWORD_DEFAULT, $options);
     }
    
     // 用户登录验证完成
     // ...
    }
    ?>

    password_verify

    说明

    boolean password_verify ( string $password , string $hash )

    注意 password_hash() 返回的哈希包含了算法、 cost 和盐值。 因此,所有需要的信息都包含内。使得验证函数不需要储存额外盐值等信息即可验证哈希。

    参数

    示例,

    ?php
    // 想知道以下字符从哪里来,可参见 password_hash() 的例子
    $hash = '$2y$07$BCryptRequires22Chrcte/VlQH0piJtjXl.0t1XkA8pw9dMXTpOq';
    
    if (password_verify('rasmuslerdorf', $hash)) {
     echo 'Password is valid!';
    } else {
     echo 'Invalid password.';
    }
    ?>

    以上例程会输出:

    Password is valid!

    PHP5.50 之前的密码哈希 API

    安东尼·费拉拉(PHP原生密码哈希 API的开发者)为PHP5.5.0 以下的版本也提供了 ircmaxell/password-compat组件(https://packagist.org/packages/ircmaxell/password-compat)。

    这个组件也实现了PHP密码哈希API中的所有函数,

    我们可以直接使用 Composer 把这个组件添加到我们的应用中就行了。例如,

    composer require ircmaxell/password-compat

    总结

    以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对脚本之家的支持。

    您可能感兴趣的文章:
    • 详解PHP处理密码的几种方式
    • php登陆页的密码处理方式分享
    • 一个简单的网页密码登陆php代码
    • php+mysql实现简单登录注册修改密码网页
    • php+MySQL实现登录时验证登录名和密码是否正确
    • php password密码验证正则表达式(8位长度限制)
    • 允许phpmyadmin空密码登录的配置方法
    • php中实现记住密码下次自动登录的例子
    • 理解php Hash函数,增强密码安全
    • php中实现记住密码自动登录的代码
    上一篇:PHP如何根据文件头检测文件类型实例代码
    下一篇:php5.5使用PHPMailer-5.2发送邮件的完整步骤
  • 相关文章
  • 

    © 2016-2020 巨人网络通讯 版权所有

    《增值电信业务经营许可证》 苏ICP备15040257号-8

    PHP中常见的密码处理方式和建议总结 PHP,中,常见,的,密码,处理,