浅谈站点注册用户密码和安全
很多朋友都会使出浑身解数,通过Session,Cookie等各种各样的方式来保存登陆用户,以便于建造像会员系统这样个性化的服务。一般而言,一个会员系统总是依靠用户名和密码来验证用户的登陆,站点要时刻记住一个会员已经登陆,并在接下来的访问中保持这个信息不丢失。通常,很多朋友的做法是,将用户名和密码作为两个值存储在Cookie中发送到客户端,在接下来的访问中检测该Cookie的值,很少人用Session,因为Session有些不稳定的因素,或者开发者考虑到了服务器可能会因此承受很大的负荷。
好,回到正题,我们姑且不论采用何种方式来追踪用户,Cookie或者Session,但是我看到的大多数站点都会把用户名和密码一起保存。而且绝大多数开发者甚至直接将密码以明文方式存储。要知道,客户端的Cookie是可以用记事本解读的,即便是使用Base64编码使他们看起来像乱码,但有些很简单的工具可以将它们解码。
有些开发者考虑了安全问题,他们设法将这些敏感信息加密。但仍然摆脱不了要将敏感信息发送到客户端或者存储。认为这样很安全也是不实际的。加密只是为了拖延非法解密的时间,别有用心者只要有足够的设备和时间,这些信息还是会被揭开,被别有用心者所利用。
那么现在有人要问了,怎么办?好吧,其实我应该反问:将密码存储发送值不值得?有没有必要?这就得从用户名说起。几乎所有网站要求注册用户名都是不能重复的,也就是说,在整个会员系统数据库中,他们是唯一的,这就是说,用户名就是会员在这个会员系统中的唯一标识。因此,追踪一个用户,使用用户名这个唯一标识就足够了。这样。密码对于追踪一个用户来说就显得多余,完全没有必要将它们发送或者存储到其他位置。密码所做的工作就是“保证输入该用户名登录的用户是不是他本人”,因为只有真正持有该用户名的用户才知道密码。
所以在接下来,用户输入用户名和密码,在数据库中存储的数据相比较,认为用户是合法正确的了,那么以后的操作追踪用户就可以依靠用户名这种唯一标识。
当然,这里还有个题外话。开发人员在设计数据库的时候,总是会习惯性地添加一个数值类型的字段来当作一个数据表的主键,这么做的目的是数据库中,数值类更适合做多个表之间的主键外键关联,计算机处理数值当然比处理一个字符串的用户名要快得多。一个会员信息表中,主键也是从来不会重复的,他同样能够代表一个用户。往往用户信息表和其他数据表之间通过主键外键建立关联,假如我们在验证用户合法后,保存的是用户名,那么我们要从其他表中查询该用户对应的信息,就还得依靠用户名从数据表中获得主键,然后再来查询关联的外键表中的数据。所以在最后,我通常建议在用户验证时,就顺带将用户所对应的主键值存储起来,而不是存储用户名。尽管他们从理论上来说都可以表示一个用户,但是在接下来的数据库查询中,我们会省去很多不必要的多表联合查询的烦恼,并且也可以减轻一些数据库的负担。
关于注册用户密码的安全,这仅是一个站在很高的高度上对编程开发的指导性思想。安全是一个很宽泛的概念,足足一本字典才能讲得完,但是说到底,结合这篇文章所论述的问题,我大概总结了以下几个原则:
1、敏感数据尽可能减少存储。要验证一个用户,存储密码是有必要的,但仅限于在数据库中保存它就足够了。因为密码仅是起到隐私验证的作用,对于标识一个用户,它没有任何作用。用户名或主键值就可以完全标识一个用户。任何时候都记住尽可能减少敏感信息的存储。
2、对于必须要存储的敏感信息,采取加密。加密是因为必须要存储敏感信息不得已才用到,任何时候都不能期望加密能够保证万无一失,也没有任何理论证明加密是牢不可破的。这一点很多开发者都意识到了。我看到的很多数据库中密码的存储都采用MD5或者SHA等不可逆的信息摘要算法来加密,这是值得认可的。不过现在MD5散列的查询数据库网上也有了,所以采用MD5直接加密密码也变得不够安全,现在通过一些加入“Salt”的方式来加强加密效果,不过这已经超出本文的范畴,所以不再讨论。
3、不要使用自创的加密算法。很多开发者乐于发明自创的加密算法,这么说等于打击开发者的信心。但是,要知道,自创的加密算法尽管可能有坚实的数理基础来证明,但是也许经不起众多别有用心者的破解。很多时候开发者容易走入误区,因为自创的加密算法,其密文的牢固度多数是建立在别有用心者不了解你的算法这样的基础上,而不是完全依赖于密钥,算法一旦公开,就极其危险。当前流行的主流加密算法,是在经过长时间的实际考验的基础上的,至少在这段时间内证明这种算法是行之有效,能够拖延破解时间或者增加破解者成本的,而他们的算法一般都是公开的。相比自创的加密算法,他们的安全性更高。
我一直都在从事商用系统的开发,商用系统不像演示系统,或者毕业作品那样。安全是在开始设计系统时就需要考虑的。而往往很多开发者忽略了这部分,开发的系统极不安全。即便没有“黑客”那样的好事者关顾你的系统,在商业竞争中,也得提防你的竞争对手来破坏你的系统。
这文章甚至和ASP.NET扯不上关系,不过也请版主不要修改或转移。在.NET中,关于安全方面,已经封装了完整的用户验证、授权访问的解决方案。具体的我也在http://bbs.bc-cn.net/viewthread.php?tid=67635&star=at#之中进行了详细描述。
之所以写这文章,是希望大家在解决技术问题的同时,不忘站在系统的高度,充分考虑各方面的问题。建造安全的系统,以营造安全和谐的网络环境。