WEB应用的安全的登录认证
前些日子看到一个关于安全登录认证的博文,不过该文提到的登录认证算法有点复杂,而且仍然存在一些安全缺陷。想到之前了解过的HMAC算法,我觉得完全可以使用基于HMAC算法来进行WEB应用的安全的登录认证。
所谓安全,其实主要是解决一个问题:在基于明文传输的HTTP协议下隐藏用户输入的密码。当然,同时还需要考虑到用户密码在服务器端同样不能以明文保存。
也许有人会想到一个最简单的想法:在服务器端把密码用HASH算法(比如MD5、SHA1、SHA256等)加密之后保存,在客户端同样对用户密码进行HASH之后再传到服务器进行验证……想法很好,不过仔细想想,这其实和明文密码没有区别,两端的HASH计算只不过是把用户密码变了个样子而已,就好像——用户输入的是HASH过后的密码,然后明文传输进行登录一样。
言归正传,考虑到服务器端需要较为安全的保存密码,可以将用户密码进行HASH,并在HASH的时候引入SALT(盐)。SALT在保存密码的时候随机生成,并随HASH的结果一起保存在服务器的数据库内。比如我们可以建这样一张用户表:
字段名 说明
username 用户名,一般不区分大小写
salt 盐,文本,随机生成
hashpass 加密后的用户密码,通过算法HASH(salt, password)生成
需要注意的是,这里在计算hashpass的时候也可以将用户名计算在内,但要考虑用户名不分区大小写时的情况,所以可以是:HASH(L_CASE(username), salt, password)
现在不考虑安全传输的情况下,用户登录验证过程可能是这样:
1. 用户输入用户名U和密码P,提交到服务端
2. 服务端通过U找到数据库中的相应的salt和hashpass
3. 使用salt计算出用户输入密码的hash值,H = HASH(salt, P),
或者是HMAC(L_CASE(U), salt, P)
4. 对比计算结果H和数据库中取出来的hashpass,如果一致,则验证成功
这里从客户端传到服务器的P是一个明文。接下来要考虑的就是把这个明文变成不可识别也不可破解的密文,当然首选HASH算法。
为什么不选DES/AES之类的对称加密算法呢——很显然的一个道理,客户端是通过JS来计算加密的,如果选用DES加密算法,用户密码在这里可能充当两种角色,一种是Key,这种情况下,要求服务端用同样的Key来解密,那么Key就需要以明文方式保存,破坏了存储密码的安全性;另外一种角色是被加密的数据,但这样一来,Key就成了能被截取的明文(由服务器明文传输过来,或直接写在JS源文件里),在有Key的情况下,DES可以直接解密,用户密码就暴露了。再深入一点思考,如果把用户密码先按服务器端的算法计算HASH,再通过DES加密输入到服务器呢?——其实HASH过程已经就把用户密码进行了不可逆的加密,再进行一次DES有何意义呢?
那么,相对安全的,按HMAC算法设计出来的登录验证过程应该是这样:
1. 客户端发消息给服务器请求登录,该消息包含用户名U
2. 服务器取得U,从数据库中检索出salt,同时产生一个随机数R,一起返回给客户端
3. 客户端进行第一次HASH算法,得到需要在服务器端验证的密码:H1 = HMAC(salt, P)
或HMAC(L_CASE(U), salt, P)
4. 客户端进行第二次HASH算法,得到需要传送回服务器的HASH值:H2 = HMAC(HASH(r), H1)
5. 客户端将H2传送到服务器
6. 服务器根据U检索到数据库中的hashpass,用同样的HASH算法计算HS = HMAC(HASH(R), hashpass)
7. 如果hashpass和客户端计算的中间数据H1一致,则HS与客户端传入的H2一致,验证成功
8. 不管验证成功与否,R被抛弃。下次登录过程由服务器重新产生新的随机数R1参与计算。
这里的安全保证在于:
1. 可以被截取或计算出来的,只有U, salt,R和H2,甚至就算数据库的hashpass被泄漏,仍然不可能计算出用户密码P。
2. 用于验证的H2不能重复使用。R作为一个临时随机数,仅在当前登录过程有效,所以R参与了计算的结果H2不能用于下一次登录。
http://www.2cto.com/Article/201303/198047.html
原文链接:https://www.cnblogs.com/shanheshui/p/4549477.html
原创文章,作者:优速盾-小U,如若转载,请注明出处:https://www.cdnb.net/bbs/archives/18225