前言
密码加密很重要,如果泄露是后台管理员的用户密码,会严重的损害系统的安全性;如果密码不加密直接明文存储到数据库,一旦数据库泄露,密码也会泄露,而大部分人在不同网站上用的密码都是一样的,黑客拿到密码便可以攻击该用户的别的网站的账号(据说之前csdn就报出密码明文存储的事情)。
密码加密很重要,但是很多人忽视了。用户的密码设置过于简单、程序员在开发时未考虑密码的加密。这一切都导致做出来的web系统让黑客进出自如。
这篇文章试图从多个角度去探讨,作为程序员,我们应该如何处理好密码,如何更好的对密码进行加密。
1、源头上遏制弱口令
众所周知,网络上常常有弱口令密码表,黑客只需要遍历弱口令表去试探密码,就可以完成这一暴力**过程。
因此一个好的方式是,从源头上拒绝弱口令的出现:
- 密码的长度应该达到8位以上
- 密码应该同时由数字、字母和其他字符组成
- 密码和用户名不应该存在联系
- 密码不应该和上一次设置的密码相似(重置密码时)
- 定时,如半年进行密码的修改
- 应该有确认密码机制,防止密码过于复杂,用户误输入
- 用户名要有最短长度限制,用户名不应该可以其他用户重名
如何进行验证?
- 前端进行验证,验证密码和确认密码一致、验证密码长度、复杂度符合要求,同时和用户名不存在强的关联(可以用KMP算法)
- 后端需要将前端验证的那几项再验证一次,因为前端的数据往往是不可信任的,通过一些方式可以很轻松的绕过前端的验证
- 后端接着校验密码和上一次设置的密码不相似
2、主动防御
我的理解是:给密码加密属于被动防御,它并没有阻止黑客进行攻击,只是增加了攻击的复杂度而已。
而主动防御则是限制用户只能从前端界面进行登录(一定程度上限制了黑客使用脚本),从而提高了密码被**的难度。
- 设置密码输入错误达到一定次数锁定账户
- 这种方式能有效的应对黑客的暴力解密
- 设置前置登录条件
- 前置登录条件指的是在登录之前必须要做一些事,才能进行登录:
- 比如说需要绘制手势密码
- 比如说要按一定顺序点击页面某些特定的地方后(这里可以在点击某些特定的地方时发送特定的请求),后端将这些点击的顺序存入缓存,满足一定顺序和正确性条件后才允许请求登录接口),这种很适合用在一些私人性质很强的系统中。保密性也不错,毕竟很少人能想到在登录之前必须要点击某些地方。
- 比如说需要从一系列图片中选择出正确图片
- 设置登录锁定IP,如果要在另一个IP登录,则需要进行手机或者邮箱验证码验证
- 直接设定每次登录都要进行手机或者邮箱验证码验证
3、简单的办法来保证密码传输时的安全性——使用HTTPS
客户端在使用HTTPS方式与Web服务器通信时有以下几个步骤,如图所示。
(1)客户使用https的URL访问Web服务器,要求与Web服务器建立SSL连接。
(2)Web服务器收到客户端请求后,会将网站的证书信息(证书中包含公钥)传送一份给客户端。
(3)客户端的浏览器与Web服务器开始协商SSL连接的安全等级,也就是信息加密的等级。
(4)客户端的浏览器根据双方同意的安全等级,建立会话**,然后利用网站的公钥将会话**加密,并传送给网站。
(5)Web服务器利用自己的私钥解密出会话**。
(6)Web服务器利用会话**加密与客户端之间的通信。
因此,使用了SSL之后,信息在传输时便已经进行了加密,明文密码在传输时也得到了加密。
很多人没有意识到有这么一个简单的方式来进行密码传输时加密。这比自己实现的简单加密安全性要高。
4、一个简单的密码验证思路
如果1、2、3步骤都做了,那哪怕密码使用明文传输,安全性也不会低了。
对于很多系统并不要求达到很高的安全性(应该基于系统和数据的重要性去研究是否使用复杂的加密手段),我们可以基于HMAC这种**哈希算法,就可以提高很多的安全性:
-
前端密码加密:
- 前端请求登录,后端回复一个随机字符串,并存在session中
- 前端使用HMAC(密码明文 + 随机字符串)=》密码密文,发给后端
-
后端密码加密:
- 后端从数据库取出AES密码密文
- AES解密获得密码明文
- HMAC(密码明文 + 随机字符串)=》密码密文
- 和前端的密文对比,正确则登录成功
5、结合验证码进行复杂加密
现在几乎所有的网站、APP都有使用登录验证码。但不是都用来进行加密。
登录验证码的主要用途:
- 防止机器人、爬虫。(多见一些图片验证码、拖曳人机验证)
- 用户身份验证,同时增加注册成本。(手机验证码、邮箱验证码)
- 保证登录的时效性。(一般登录验证码都有时效)
- 结合密码进行加密
基于验证码,我们能够得到一种较安全的加密思路:
-
前端注册加密规则:
- 从后端获取RSA公钥
- 生成一个随机的AES**
- RSA加密(AES**,RSA公钥)=》AES**密文、
- AES加密(密码明文 + 验证码, AES**)=》密码密文
- 将AES**密文和密码密文发给后端
-
后端注册获取密码:
- RSA解密(前端传的加***,RSA私钥)=》 AES**、
- AES解密(密码密文, AES**)=》密码明文 + 验证码
- 对密码明文进行验证,如长度、数字字母要求等
- SHA256加密(密码明文)=》密码密文 (如果需要保存明文,可以不要这一步)
- AES加密(密码密文,后端存储的AES**)=》二重密文
- 二重密文 =》 数据库
-
前端登录加密规则:
- SHA256(SHA256(用户名 + SHA256(密码)) + 验证码)三重hash加密
-
后端登录验证加密规则:
- 从数据库取出二次加密密码密文,即:AES加密(密码密文,后端存储的AES**)
- 解密得到密码密文,AES解密(密码密文,二次加密密码密文)=》密码密文,即SHA256(密码明文)
- 从缓存读取验证码,如果过期则返回验证码已过期
- SHA256(SHA256(用户名 + 密码密文) + 验证码)=》模拟前端进行加密
- 将加密的结果和前端传过来的密码进行对比
- 对比成功,返回登录成功,反之登录失败
-
为什么要进行前端加密?
-
简单说就是前端到后端的这段过程密码很可能被拦截。
-
为什么前端加密要多重加密,并用验证码加盐?
-
多重加密使得密码更加复杂,同时能糅合用户的用户名信息,提高唯一性、糅合验证码,提高时效性。
-
为什么前端注册要用RSA进行非对称加密?
-
因为不管怎么对前端的密码进行加密,都可能被拦截,从而获取到密码或者密码密文。黑客利用这个密码或者密码密文就可以模拟前端进行登录(越过前端的加密,直接发密文)。而用了RSA之后,配合随机生成的AES**,黑客得不到RSA私钥,几乎无法**得到密码的明文。
-
为什么密码存到数据库之后还要进行哈希加密,然后进行AES加密?
-
这只是最后一道手段,因为假设黑客已经黑入了数据库(通过sql注入或者别的什么方式),此时所有的密码都会在他的眼前,他可以通过这些密码,达到登录的目的。而如果再加一层AES加密,并将AES**存储在文件中而不是数据库中,黑客几乎无法利用这些密码。别提解析明文,连用来登录此系统都有难度。
-
密码验证通过之后就无忧了吗?
-
错,基于跨域攻击获取cookie的方式,或者拦截获取token的方式,黑客仍然可以伪造用户已登录的状态。通过文件上传漏洞,黑客可以运行脚本,控制服务器。通过xss攻击进行js注入,可以将用户的信息发到自己的网站。因此,web安全永远是木桶效应——你能达到的安全性取决于你的短板,而不是你做的最好的那个方面。
-
为什么登录中不用RSA加密?
-
RSA加密解密速度较慢,如果系统用户不多,或者登录的响应速度不是最重要的点,就可以考虑每次登录都用RSA进行加密。
参考&引用
为什么HTTPS比HTTP安全,以及两者的优缺点
https://www.cnblogs.com/zhangsanfeng/p/9125732.html