“山寨”SESSION讨论
把用户状态用SESSION存在服务端还是用COOKIE存在客户端?一直有这个困惑但从未静下心来仔细思考。直到最近项目告一段落才得以清闲几日,整理了一下自己的想法,描述出来抛砖引玉,请各位指正和讨论。
案例描述:把场景精减,假设一个简单的会员系统,输入账号、密码登录后产生会员ID,并以会员ID作为登录凭证。
OK,上面的情形我想每个WEB开发者都遇到过,首先是使用Cookie存在的安全问题:
如果这是一个涉及支付的会员商城系统,用户篡改了客户端会员ID,那么就代表他能以任何其它人身份登录,我想这一定是致命的。很多开发者的做法是用可逆加密算法对COOKIE加密,比如3DES。但想想其实用户是能拿到加密前和加密后的数据的,这种情况我想再强大的加密算法也不会让人踏实。之前在网上还看到一些利用HTTP技巧对COOKIE进行处理的文章,但HTTP本身就是明文传输,这类解决方法我想也只能是治标不治本。
似乎安全是COOKIE不可逾越的一道障碍,如果换用SESSION呢:
我想99.99%的人还是不能破解SESSION的安全机制吧,SESSION在客户端存放了一个KEY,在服务端存放了真实数据,要获取真实数据就需要提供KEY,在物理上对数据进行了隔离。OK,SESSION是安全的。但假设我要对SESSION的规则做一些自定义的修改呢?比如常见的“记住密码”功能,让会员ID一直在服务端保留;比如去除超时限制,让SESSION像COOKIE一样可以不存在超时呢。很遗憾,微软对SESSION做了完美的封装,我能做的只有赋值和读取。写这篇文章的动机也就是因为遇到了如上的问题,再加上一直有着“山寨”情节,且山寨一个自定义的SESSION,请各位指正。
解决方案(如下图):
当会员登录后在客户端生成COOKIE值:会员ID和KEY。KEY将作为安全验证核心,同时在服务端Cache中添加KEY与会员ID的对应关系。当用户每次访问要求安全验证的页面时都必须提供KEY。如果在CACHE中存在KEY则允许访问,否则禁止访问。
之前准备将服务端的数据存放在数据库中,就像.NET提供的SESSION StateServer或SESSION SQLServer模式,但数据库与内存,两者在速度和性能上都差距颇大,权衡后决定用Cache+HashTable来实现。
然后我的项目有一个“记住密码”功能,所以KEY就要求在客户端用COOKIE长期保留,同时在服务端的数据库用一张表来记录这些“记住密码”的用户,表中包含了一个“过期时间”字段,单独的WIN服务程序定时清空过期的记录。最后让应用程序启动时把“记住密码”的这批用户KEY添加到CACHE中。
大概思路就是如此,套用了SESSION的原理,一些细节还未考虑周全,先将想法拿出来请各位指导一下,后面再开始编码实现。