HTTP协议下保证登录密码不被获取更健壮方式
说到在http协议下用户登录如何保证密码安全这个问题:
小白可能第一想法就是,用户在登录页面输入密码进行登录时,前台页面对用户输入的密码进行加密,然后把加密后的密码作为http请求参数通过网络发到服务器。
这样做是无法保证用户的账户安全的,因为稍微懂一点编程知识的人就可以通过你发送的http请求知道了你的密码,小白又说了,我密码加密了,它拿到的也是加密后的密码,它不知道我的原始密码它是无法从登录页面登录的。
原文和作者一起讨论:http://www.cnblogs.com/intsmaze/p/6009648.html
新浪微博:intsmaze刘洋洋哥
但是小白啊,你有没有想过,有时候我仅仅知道你加密后的明文就够了,我可以自己伪造http请求,把明文加在请求参数里面,一样可以登录系统的。
大白这时候有话说了,大白:我可以对密码进行加盐。好,我们先看加盐是什么,加盐简单说就是程序对用户设置的原始密码后面追加随机数来加强用户密码的复杂性,然后再对组合后的密码进行加密进行存储,用户每一次登录,前端先对用户输入密码进行加密传输到后端,然后后端获得用户账号到数据库找到该用户的盐,再和传来的明文组合一起进行一次加密后与数据库中的密码进行对比来判断是否是符合用户。但是啊,大白,你看,这样做,并无法控制其他人通过你http请求获得明文,获得后,人家照样大摇大摆使用你的身份登录系统进行操作。
好,大白让我跟你讲讲加盐的真正意义:加盐的意义不是为了保证密码在网络传输的安全性,而是防止数据库被人入侵后,由于原始密码太过简单,被人分析出来,进而知道了密码。直接对密码进行MD5处理后,反向解密确实难度很大,但还是可以找出破绽的 例如:两个人或多个人的密码相同,通过md5加密后保存会得到相同的结果。破一个就可以破一片的密码。如果用户可以查看数据库,那么他可以观察到自己的密码和别人的密码加密后的结果都是一样,那么,别人用的和自己就是同一个密码,这样,就可以利用别人的身份登录了。那么我们以前的加密方法是否对这种行为失效了呢?其实只要稍微混淆一下就能防范住了,这在加密术语中称为“加盐”。具体来说就是在原有材料(用户自定义密码)中加入其它成分(一般是用户自有且不变的因素),以此来增加系统复杂度。当这种盐和用户密码相结合后,再通过摘要处理,就能得到隐蔽性更强的摘要值。
小黑说:你说的这些我都懂,我来告诉你最终的方案吧:在用户输入完账号后,后台ajax发送用户的账号到服务器,这个时候服务器为该账号生成一个随机数验证码,响应给前端登录页面。
当用户输入密码后,前端页面对用户输入的密码进行加密,然后把加密后的明文和获得服务器返回的验证码组合在一起再一次进行加密。然后把该信息发送到服务器,服务器session中保存这这个账号的验证码,服务器会从数据库获取该用户的密码和验证码进行组合再次加密与前端传来的明文进行对比判断。
好,接着让我们分析为什么安全,因为验证码是一次性的,, 所以,你在网络层拿到本次的请求之后,无法做 重放攻击, 因为验证码是不正确的.而当你获取新的验证码, 但你并不知道 组合之前的内容[md5(md5(密码) + 用户的QQ号)] 是什么 , 所以你无法重新发送本次请求实现登陆的目的.32位MD5 + 4位验证码 总计 36位的字符串, 你去破解吧. 估计等你挂了你也破解不出来.至于服务端的校验, 只要将记录下来的MD5值(而不是记录的明文), 进行同样的运算, 得到的结果与提交上来的一样, 即密码正确.验证码的内容是服务器下发的,而且是一次性的,所以 客户端无法伪造, 也无法重用.
下面是QQ之前网页的源代码片段:
Q 网页上的登陆模块(全程HTTP/GET请求).
QQ 在登陆时,对用户输入的密码加密的JS代码为:
function getEncryption(password, uin, vcode, isMd5) { var str1 = hexchar2bin(isMd5 ? password : md5(password)); var str2 = md5(str1 + uin); var str3 = md5(str2 + vcode.toUpperCase()); return str3 }
白话就是: md5(md5(md5(密码) + 用户的QQ号) + 验证码)
现在你知道如何在http协议下保证密码安全性了没有。
然后我们在说说用户登录后,我们是否要把用户的密码保存到session中。
以前同事写的密码修改部分代码,发现将用户登录的密码存在session中,然后判断原密码时直接从session中读取。
session的保存方式相对来说比较安全,因为信息存储在服务器的
而cookie的方式由于对服务器端来说是不可控的,始终对用户信息泄露是一个危险,但是也有很多采用cookie存储用户信息的,通常是采用加密的方式来进行处理。
我们经常看到很多网站设置记住用户名密码,就是采用cookie的方式
可行性上,我不建议这么做。就连sun公司在是设置password的时候,都用transient 来管理, private transient String password;都不希望password序列化掉, 所以我们跟不能为了方便而把密码存入session中来为了方便。
在网页提交(其实所有的通信都有这个问题)密码这个问题上,需要有几个维度来保证安全,
我想哭呀,我打算下一篇跟大家介绍数字签名和公钥私钥等,虽然我不是专做网络通信的,但是我对计算机网络的基本知识还是具备的,再结合开发角度来谈谈。就不能给点鼓励吗!