我的编程空间,编程开发者的网络收藏夹
学习永远不晚

php中密码的加密处理及安全措施

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

php中密码的加密处理及安全措施

在数据库中保存明文密码是非常不明智的选择,其危害不言而喻。

这里就不讨论明文密码的缺点了,只谈谈如何安全的保存密码。

基本的安全措施如下:

1.设置密码最小位数

2.将用户的密码加密保存

3.通过重置密码的一次性链接修改密码

4.同一IP或mac地址一天内只能获取3次重置邮件

5.用户修改密码时需输入原密码

6.用户信息被修改后发送短信/邮件提醒

当然还可以采取更安全的措施:

7.不常用设备登陆需手机短信验证(需要短信平台)

8.设置安全问答信息

9.记录错误登陆请求信息,多次错误后拒绝登陆尝试

--------------------------------------------------------------------------

第一项:密码的加密保存

通常情况下md5是最常用也是最简单的,但也是破解方法最多的一种方法。

php 5.5及以上版本中提供了Password Hashing API, 非常方便的解决了密码加密问题

http://tw2.php.net/manual/zh/ref.password.php

密码加密

<?php
//$hash就是密码加密后的字符串
$options = [
    'cost' => 10
    //'salt' => mcrypt_create_iv(22, MCRYPT_DEV_URANDOM), 不推荐手动设置盐值
];
$hash = password_hash("123456", PASSWORD_BCRYPT, $options);
?>

注意手动设置盐值在这里不被推荐,在php7里已经废掉这个选项。

password_hash中的第二个参数是对算法的设置,有两个选项:

  1. 默认为PASSWORD_DEFAULT,现在的算法为bcrypt, 但这个算法会随着php版本的更新而更新更强的算法,建议数据库字段设置为char(255)。

  2. PASSWORD_BCRYPT,算法也是bcrypt,(手册上写的CRYPT_BLOWFISH,其实就是crypt()使用CRYPT_BLOWFISH算法),结果永远是60个字符串,字段设置为char(60)即可。

简单的说password_hash就是把bcrypt封装了起来,而且会随着以后版本的更新而改进提升所使用的算法,就现阶段来讲,bcrypt已经足够安全了。

-------------------

顺道解释一下什么是 cost(消耗) 和 salt(盐值)

cost:消耗--是用来对付暴力破解的,随着计算机速度的不断提升,我们可以让一台计算机几十年不关机来破解一个密码,所以我们人为的加上一个消耗值,使计算机的算法变慢一点,当然变慢的这一点对单次运算影响不大,但暴力破解时间就要延长到几千上万年了。

salt:盐值--用于对付彩虹表(不知道自行百度一下),盐值作为一个干扰项,使每次hash产生的密文均不相同,抵御彩虹表破解。

-------------------

密码验证

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

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

//检查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以下版本,可用以下方法(也是我现在使用的方法,原理上是一样的)替代:

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);

    }
    
}

-------------------------

第二项:密码的一次性的重置链接

一次性链接有这么两特点:

  1. 在链接生成的一定时间内(比如24小时)点击有效

  2. 一旦密码被重置,链接立即失效

既然这样,就需要记录链接的是否过期,有以下几种思路:

  1. 数据库中保存链接生成时间和链接是否已被使用(考虑用一个字段记录信息)。

  2. 利用opcode缓存,需要安装xcache或其他类似工具

我现在用的便是xcahce,主要考虑到保存到库中会增加开销。

public function generate_link($username,$hash){

        if (function_exists('xcache_isset')) {

            //将username加密作为我们的unique_id
            $unique_id = md5($username);
            
            //将username保存到名为unique_id的缓存中,设置缓存24小时候过期
            xcache_set($unique_id, $username, 24*60*60);
            
            //将username和hash加密作为验证信息(不放心的话可以在加一个公匙在里面)
            $validate = md5($username.$hash);
            
            //拼接成字符串
            $string = $unique_id.$validate;

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

            return $link;

        }

    }

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

        if (function_exists('xcache_isset')) {

            //获取链接中的unique_id
            $unique_id = substr($p, 0, 32);

            if(xcache_isset($unique_id)){

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

                //获取链接中的验证信息
                $link_md5 = substr($p,32);

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

                    //链接验证成功

                }else{

                    //链接验证失败
                    redirect();

                }


            }else{

                redirect();
            }

        }

    }

记住密码重置后要立即清除$unique_id的缓存

if(updateLoginPassword($username,$password)){
     xcache_unset($unique_id);
}

第三项:设置同一IP一天内的重置密码次数限制

和一次性链接很像,也有两种思路:

  1. 将ip存到数据库

  2. 将ip信息通过xcache保存

我就只给大家提供一个获取ip的函数了,其他的大家自己补充吧

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"];
   }

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

php中密码的加密处理及安全措施

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Perl中怎么处理加密和安全性

在Perl中处理加密和安全性通常使用Crypt::OpenSSL模块。这个模块提供了一系列加密算法和哈希函数,可以用来进行数据加密和解密,以及生成和验证数字签名等操作。另外,也可以使用Perl的Digest模块来计算数据的哈希值,以保证数据
Perl中怎么处理加密和安全性
2024-03-05

Swoole和Workerman对PHP与MySQL的数据加密和安全性的处理能力

随着互联网的快速发展,数据安全问题变得越来越重要。在PHP与MySQL的开发中,数据加密和安全性的处理是不可忽视的一项任务。本文将介绍PHP开发中两个流行的网络通信框架Swoole和Workerman,以及它们在数据加密和安全性处理方面的能
2023-10-21

如何使用安全的密码管理工具保护CentOS系统中的密码

要保护CentOS系统中的密码,可以使用以下步骤和工具来管理密码:1. 使用强密码:确保您的密码是足够强大和复杂的,包括字母、数字和特殊字符的组合。避免使用常见的密码和个人信息作为密码。2. 使用密码管理工具:使用密码管理工具可以帮助您创建
2023-10-10

如何解决PHP开发中的数据安全和加密存储

随着互联网的普及和应用程序的发展,数据安全和加密存储变得越来越重要。在PHP开发中,我们需要采取一些措施来确保敏感数据的安全性,以防止潜在的攻击和数据泄露。本文将介绍一些常用的方法和实例,帮助您在PHP开发中解决数据安全和加密存储的问题。使
2023-10-21

帝国CMS管理员帐号、密码、认证码及安全答案忘记的解决办法

忘记后台管理员帐号怎么办? 用phpmyadmin查看phome_enewsuser表里的记录:查看use编程客栈rname字段的内容. 忘记后台登陆密码怎么办? YUuJrwHNS用phpmyadmin修改phome_enewsuser表
2022-06-12

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录