比较天真的实现方式:将登录凭证、权限信息等保存到Cookie中。
真的是很可怕,本站之前使用的老ASP博客系统就是这么实现的。
最终导致系统被黑,网站被挂马。。。。。
这次开发的新系统考虑到这种教训,采用了比较安全的实现方式。
1,在用户密码的存储和验证方面使用了安全性较高的实现方案。
具体实现方式在之前的文章中有详细介绍。
a. 对密码强度进行要求。 参考 简单实现js密码强度检测,友好的html css样式提示
密码要求至少8位,大小写字母数字标点符合至少包含三种。
保证密码的基本安全性。
b. 对密码采用安全的hash加密存储。参考 在PHP程序中实现安全的用户密码保存-加密存储和登录验证
密码安全存储是为了应对数据泄漏风险。
a. 对密码强度进行要求。 参考 简单实现js密码强度检测,友好的html css样式提示
密码要求至少8位,大小写字母数字标点符合至少包含三种。
保证密码的基本安全性。
b. 对密码采用安全的hash加密存储。参考 在PHP程序中实现安全的用户密码保存-加密存储和登录验证
密码安全存储是为了应对数据泄漏风险。
2,在登录时进行暴力破解预防
最基本的两项就是 验证码 和 密码试错次数限制。
验证码功能可以参考之前的文章 在CodeIgniter4中集成谷歌验证码 reCaptcha V2
关于密码错误次数的限制,网上有一些天真的利用 Session 记录错误次数的实现代码。
那样是完全没有效果的。
错误次数可以在数据库中记录,也可以在Memcache,redis等缓存中记录。
CodeIgniter4有缓存模块,我们这里可以直接利用它自带的缓存模块实现
根据用户名来记录密码错误次数信息,在登录时先判断错误次数。次数超过时直接报错。
然后进行登录验证,密码失败时,调用辅助函数记录次数。
验证码功能可以参考之前的文章 在CodeIgniter4中集成谷歌验证码 reCaptcha V2
关于密码错误次数的限制,网上有一些天真的利用 Session 记录错误次数的实现代码。
那样是完全没有效果的。
错误次数可以在数据库中记录,也可以在Memcache,redis等缓存中记录。
CodeIgniter4有缓存模块,我们这里可以直接利用它自带的缓存模块实现
[复制到剪贴板] |
/**
* 判断是否超出了最大错误次数
* 2小时内错误5次
*/
function password_CheckErrors($username):bool{
$key = 'passErr_' . $username ;
$data = cache($key)?? 0;
if($data >= 5)
return true;
return false;
}
/**
* 记录错误次数
*/
function password_addErrors($username): int{
$key = 'passErr_' . $username ;
$data = cache($key) ?? 0;
$data++;
cache()->save($key, $data, 7200);//2小时
return $data;
}
/**
* 获取当前错误次数
*/
function password_getErrors($username):int{
$key = 'passErr_' . $username ;
$data = cache($key)??0;
return (int)$data;
}
根据用户名来记录密码错误次数信息,在登录时先判断错误次数。次数超过时直接报错。
然后进行登录验证,密码失败时,调用辅助函数记录次数。
3,安全的使用Cookie保存登录状态
首先,绝对不能将用户凭证权限等信息保存到Cookie中。
我们可以在Cookie中保存一个没有实际意义token标识。同时将这个token标识,过期信息保存到数据库中和用户关联。
在用户登录成功后通过上面的辅助函数生成一个随机token。
在用户下次访问时直接获取token值,然后从数据库中查询是否有关联用户。
如果找到用户,先判断是否过期,然后实现自动登录,并从数据库中获取用户权限等信息。
如果考虑更严格安全一点,也可以在数据库中记录用户的IP地址,UserAgent等信息,要求完全匹配才给登录。
我们可以在Cookie中保存一个没有实际意义token标识。同时将这个token标识,过期信息保存到数据库中和用户关联。
[复制到剪贴板] |
/**
* @param $length 生成的Token字符长度
* @return 返回生成的Token字符串
*/
function password_generateToken(int $length = 20): string{
return bin2hex(random_bytes($length));
}
在用户登录成功后通过上面的辅助函数生成一个随机token。
在用户下次访问时直接获取token值,然后从数据库中查询是否有关联用户。
如果找到用户,先判断是否过期,然后实现自动登录,并从数据库中获取用户权限等信息。
如果考虑更严格安全一点,也可以在数据库中记录用户的IP地址,UserAgent等信息,要求完全匹配才给登录。
4,自动登录Token的注销
在用户进行密码修改后要主动从数据中删除token值,避免安全漏洞。
在用户 点击 退出登录 后,也要主动注销token值,同时注销Session。
这一点很重要,可以保证用户在公共场合登录帐号后能安全退出。
在用户退出后不会给Cookie劫持或者Session劫持攻击机会。
在用户 点击 退出登录 后,也要主动注销token值,同时注销Session。
这一点很重要,可以保证用户在公共场合登录帐号后能安全退出。
在用户退出后不会给Cookie劫持或者Session劫持攻击机会。
5,最后,敏感操作要重新验证用户密码
如用户修改密码、邮箱、绑定手机号等情况,需要重新验证用户,以保证安全。