网站该如何存储用户的密码

2014-01-22 14:45:33
对那些有用户系统的网站来说,如果存储用户的密码是个问题。 大家都知道不能明文存储,这样一旦被脱了裤子,后果很严重, 简单的md5 sha加密也不可取......
通常在做网站的时候,如果有用户系统的话,那么就会涉及到保存用户信息的功能,

最基本的用户名、密码是一定要保存的,

那么如何保存密码,是我们每一个web开发者都应该思考的事情。


网上时不时的爆出一些网站被拖库的事情,其中不乏一些我们眼里的大网站,

令人大跌眼镜的是,有不少网站还在明文保存密码。


所谓明文,就是把用户密码原封不动的保存起来, 这种做法显而易见是不安全的,一旦你的数据库被拖库(拖库是指数据库内容被下载),那就将是灾难,

再加上用户的习惯性和惰性,很多用户在多个网站上都会使用同样的密码,这也会威胁到用户在其他网站上的安全。

还记得csdn600万,天涯4000万吗


明文保存的user表

id username password createtime
10001   test1@hutuseng.com    iloveu 1393151535
10002 test2@hutuseng.com hutuseng123   1393134647  


所以我们不能明文保存,需要将用户密码加密,通过算法将明文密码进行编码,用我们的函数y=f(x)表示的话,

x表示原始密码,y表示加密后的密码,f 就是我们需要的加密函数,

加密函数的设计就看自己的了,比如一个简单的加密算法就是将原始密码倒排,

举例来说,你的原始密码为 abc123 ,那么加密之后的密码就是 321cba, 

这样黑客得到你的密码的话,如果直接使用 321cba登录是无法登录的。



简单加密保存的user表

id username password createtime
10001   test1@hutuseng.com    uevoli 1393151535
10002 test2@hutuseng.com 321gnesutuh   1393134647  



但是,这样的问题就是,如果黑客知道了你的加密算法f,他很容易就能够通过f和y来反推出x。

所以,我们需要找到一种不可逆的加密算法,也就是说即使黑客知道了y和f,也是无法反推出x的。

于是md5  sha1 sha256等哈希算法就出现了,通过这些哈希算法加密后的密码,很难反推了,这些算法的逻辑太过复杂,可以找专门的资料看看。


md5加密保存的user表

id username password createtime
10001   test1@hutuseng.com    edbd0effac3fcc98e725920a512881e0 1393151535
10002 test2@hutuseng.com 46b54a029136318e9846e1c35f19db06   
1393134647  


那么我们是不是就可以把密码直接用这类算法加密存储了呢?

当然,最好不要。理由就是,虽然这些算法不可逆,但是他们很容易被暴力破解(暴破)。

暴力破解的原理就是,y=md5(x), 既然无法反推,那么就挨个试,

通常黑客们会采用一些密码字典,挨个把密码用md5算法算一遍,看看结果跟y是否一致。

由于现在的电脑性能都很强,而且MD5算法本身也很快,所以如果你的密码设计不是特别复杂的话,是很容易破解的。


现在,暴力破解这一步都省了,很多人把很多常用的密码的md5啊 sha加密后的密码都对应起来了,做成了网站,

你只管上网去查就行了,一般简单的密码都可以瞬间破解。

比如 www.cmd5.com 之类的网站,你可以上去试试,edbd0effac3fcc98e725920a512881e0 解密以后是不是就是 iloveu 呢

所以,为了防止简单的密码被破解,很多网站会要求用户的注册密码设置的尽量复杂一些,比如最少8位,要包括大小写字母、数字、特殊符号等,这样就会大大的增加暴力破解的成本。


那么按照这个思路,

如果我们不限制用户的密码复杂度,可以允许用户使用诸如123456之类的简单密码的话,

那么我们就需要把用户的密码加工一下,变成一个复杂的密码,

一个很简单的思路就是,你可以给用户密码增加一个额外的字符串a,比如 88zz%%,

这样的话,加密算法就变成了, y=md5(x+a), 如果用户密码为123456的话,

那么加密后的密码则是 12345688zz%% 这个密码的md5值,能有效的防止这种通过暴力破解和一些网站碰撞破解。


这里的这个额外的字符串a,在英文的叫法里一般叫 salt,也就是盐的意思,给密码加点盐,让它更安全。



md5加salt加密保存的user表

id username password createtime
10001   test1@hutuseng.com    d80dfeadf1181325a22cafba4d5b4782 1393151535
10002 test2@hutuseng.com 010b5eb7da3452f0a2281f185c30e8a2 
1393134647  



当然,进一步讲, 我们也可以让每个用户的salt也都不一样,来进一步的增强安全性。

比如每个用户的salt都是他的 createtime 。

还可以通过多轮md5加密的方式, y=md5(md5(md5(md5(x))))