设为首页 收藏本站
查看: 880|回复: 0

[经验分享] php中密码的加密处理及安全措施

[复制链接]
累计签到:1 天
连续签到:1 天
发表于 2016-5-26 09:02:23 | 显示全部楼层 |阅读模式
在数据库中保存明文密码是非常不明智的选择,其危害不言而喻。
这里就不讨论明文密码的缺点了,只谈谈如何安全的保存密码。
基本的安全措施如下:
1.设置密码最小位数
2.将用户的密码加密保存
3.通过密码重置的一次性链接修改密码
4.同一IP或mac地址一天内只能获取3次重置邮件
5.用户修改密码时需输入原密码
当然还可以采取更安全的措施:
6.不常用设备登陆需手机短信验证(需要短信平台)

7.设置安全问答信息
8.记录错误登陆请求信息,多次错误后拒绝登陆尝试
--------------------------------------------------------------------------
第一项:密码的加密保存
通常情况下md5是最常用也是最简单方法,但也是破解方法最多,最不安全的一种方法。
php 5.5及以上版本中提供了Password Hashing API, 非常方便的解决了密码加密问题
http://tw2.php.net/manual/zh/ref.password.php
密码加密
1
2
3
4
5
6
7
8
<?php
//$hash就是密码加密后的字符串
$options = [
    'cost' => 10
    //'salt' => mcrypt_create_iv(22, MCRYPT_DEV_URANDOM), 不推荐手动设置盐值
];
$hash = password_hash("123456", PASSWORD_BCRYPT, $options);
?>



注意手动设置盐值在这里不被推荐,在php7里已经废掉这个选项。
-------------------
顺道解释一下什么是 cost(消耗) 和 salt(盐值)
cost:消耗--是用来对付暴力破解的,随着计算机速度的不断提升,我们可以让一台计算机几十年不关机来破解一个密码,所以我们人为的加上一个消耗值,使计算机的算法变慢一点,当然变慢的这一点对单次运算影响不大,但暴力破解时间就要延长到几千上万年了。
salt:盐值--用于对付彩虹表(不知道自行百度一下),盐值作为一个干扰项,使每次hash产生的密文均不相同,抵御彩虹表破解。
-------------------

密码验证
1
2
3
4
5
6
//$hash,从数据库里读取的加密字符串
if (password_verify('password', $hash)) {
    //验证通过
} else {
    //验证错误
}



检查加密措施是否需要升级

1
2
3
4
//检查hash是否由bcrypt加密,如果不是则需要升级,返回true
if (password_needs_rehash ($current_hash, PASSWORD_BCRYPT)) {
   $new_hash = password_hash($password, PASSWORD_BCRYPT)
}



获取加密信息

password_get_info只能用于password_hash生成的hashing

-----------------------------------------------
如果你使用的是php5.5以下版本,可用以下方法(也是我现在使用的方法,原理上是一样的)替代:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class Password {

    private static $algo = '$2a', $cost = '$10';
     
    public static function unique_salt() {

        return substr(sha1(mt_rand()),0,22);

    }

    public static function hash($password) {

        return crypt($password,
            self::$algo .
            self::$cost .
            '$' . self::unique_salt());

    }

    public static function check_password($hash, $password) {

        $full_salt = substr($hash, 0, 29);

        $new_hash = crypt($password, $full_salt);

        return ($hash === $new_hash);

    }
     
}



-------------------------
第二项:密码的一次性的重置链接
一次性链接有这么两特点:
  • 在链接生成的一定时间内(比如24小时)点击有效
  • 一旦密码被重置,链接立即失效

既然这样,就需要记录链接的是否过期,有以下几种思路:
  • 数据库中保存链接生成时间和链接是否已被使用(考虑用一个字段记录信息)。
  • 利用opcode缓存,需要安装xcache或其他类似工具

我现在用的便是xcahce,主要考虑到保存到库中会增加开销。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
public function generate_link($username,$hash){

        if (function_exists('xcache_isset')) {

            $unique_id = md5($username);
            
            xcache_set($unique_id, $username, 24*60*60);

            $string = $unique_id.md5($username.$hash);

            //生成重置密码的链接
            $link = $_SERVER['SERVER_NAME']."/reset-password?p=".$string;

            return $link;

        }

    }

//检查链接是否合法
public function check_link($p){

        if (function_exists('xcache_isset')) {

            $unique_id = substr($p, 0, 32);

            if(xcache_isset($unique_id)){

                $username = xcache_get($unique_id);

                $hash = findHashByUsername($username);//通过username读取hash

                $link_md5 = substr($p,32);

                if($link_md5 === md5($username.$hash)){

                    //链接验证成功

                }else{

                    redirect();

                }


            }else{

                redirect();
            }

        }

    }



记住密码重置后要立即清除$unique_id的缓存
1
2
3
if(updateSchoolLogin($username,$password)){
     xcache_unset($unique_id);
}



第三项:设置同一IP一天内的重置密码次数限制
和一次性链接很像,也有两种思路:
  • 将ip存到数据库
  • 将ip信息通过xcache保存

我就只给大家提供一个获取ip的函数了,其他的大家自己补充吧
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
public static function validip($ip) {
        if (!empty($ip) && ip2long($ip)!=-1) {
            $reserved_ips = array (
            array('0.0.0.0','2.255.255.255'),
            array('10.0.0.0','10.255.255.255'),
            array('127.0.0.0','127.255.255.255'),
            array('169.254.0.0','169.254.255.255'),
            array('172.16.0.0','172.31.255.255'),
            array('192.0.2.0','192.0.2.255'),
            array('192.168.0.0','192.168.255.255'),
            array('255.255.255.0','255.255.255.255')
            );
            foreach ($reserved_ips as $r) {
                $min = ip2long($r[0]);
                $max = ip2long($r[1]);
                if ((ip2long($ip) >= $min) && (ip2long($ip) <= $max)) return false;
            }
            return true;
        } else {
            return false;
        }
    }

public static function getip() {
        if (self::validip($_SERVER["HTTP_CLIENT_IP"])) {
            return $_SERVER["HTTP_CLIENT_IP"];
        }
         
        if(isset($_SERVER["HTTP_X_FORWARDED_FOR"])){
            foreach (explode(",",$_SERVER["HTTP_X_FORWARDED_FOR"]) as $ip) {
                if (self::validip(trim($ip))) {
                    return $ip;
                }
            }
        }
         
        $keys = array("HTTP_X_FORWARDED","HTTP_FORWARDED_FOR","HTTP_FORWARDED");
         
        foreach ($keys as $key){
            if (self::validip($_SERVER[$key])) {
                 return $_SERVER[$key];
            }
        }
         
        return $_SERVER["REMOTE_ADDR"];
   }



运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-221914-1-1.html 上篇帖子: php的部分安装参数说明 下篇帖子: php 使用tcpdf库输出pdf 加密 密码
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表