当前位置:编程学习 > C#/ASP.NET >>

“山寨”SESSION讨论

“山寨”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的原理,一些细节还未考虑周全,先将想法拿出来请各位指导一下,后面再开始编码实现。 --------------------编程问答-------------------- 谢绝灌水,谢绝帮顶,无实质内容谢绝给分,谢谢合作。 --------------------编程问答-------------------- 你还不如直接用cache记录用户信息呢,这样全在服务器内存中,只要cache还存在,肯定是安全的,不过占用服务器内存太大

关键点时,用Cookie的话,即使服务器重启了,即使Cache没有了,他还是可以根据用户名去自动登录

睡觉了,明天来看高手的回答

--------------------编程问答-------------------- 实际上你要做的是分配给用户一个登录票据...该票据某种算法根据用户登录信息生成的唯一标识,其中不包含用户ID和密码等关键信息...服务器维护和分发此票据,用户登录后将此票据存入Cookies...至于服务器端你用Session还是Cache其实无关紧要...

当然这样做也无法保证客户端伪造登录票据,不过相对难度会大很多...除非使用证书和SSL传输,安全总是相对的... --------------------编程问答-------------------- 个人感觉用服务器端Cache,客户端用Cookies加密,这样做双重保险 --------------------编程问答-------------------- 单考虑客户端的话,只用ms给的 验证票应该就可以了。 --------------------编程问答-------------------- 我一直用加密用户所有信息,然后存入COOKIE的方法,觉得还可以。 --------------------编程问答--------------------
好复杂 --------------------编程问答-------------------- Cache本身就有过期时间,不需要WIN来清吧
用户多的时间服务器内存也是个问题
客户端清除Cookies的话会导致垃圾Cache没法及时清除
你的Key是否就是安全的,是否能伪造
Cookies加密是否比不过你的Key
真要做的很安全可以考虑SSL

--------------------编程问答-------------------- 楼主的想法完全可以用COOKIE来做,把数据加密下写里.再保险点就在Cache里再写点东西.
还有楼上说的SSL,其实SSL是一种传输加密在web.config里设一下就可以.和LZ所说的好象没什么关系. --------------------编程问答-------------------- 是的,记住密码还是用COOKIE放在本地的,想安全点,只有服务器端根据用户密码,姓名自动分配一个唯一标识符给客户端,这样就不会泄露,但还是相对的 --------------------编程问答-------------------- 问题不是在session的安全不安全上,而是在存session之前数据是否安全,之前的操作或传输前如果已经被用户窃取一切都不安全了 --------------------编程问答-------------------- 学习 --------------------编程问答-------------------- mark --------------------编程问答-------------------- 个人感觉还是加密,然后存cookie比较好,数据库中可以存在两个id,一个md5加密的。 --------------------编程问答-------------------- --------------------编程问答-------------------- 首先,你这样做,用不用key,安全级别是完全一样的。

不管是通过何种方式,我只要能搞到别人电脑上的cookie,
就是说得到id跟key对应的cookie值,那么我就可以丛任何地方来用该cookie来跳过登录直接访问你的系统了。

其次,要解决这个问题,我给你提供一下我们公司目前的解决方案把。
1,客户端存一个简单的cookie,存放加密后的id就够用了。
2,需要自动登录的用户,需要安装一个activex插件,安装成功后,取得用户的电脑标识号,存入数据库就可以了。
3,用户自动登录的时候,取得cookie里的id和用activex插件取得电脑标识号,跟数据库中的比较即可。
4,activex插件取得电脑标识号,可以这样获得:sin=md5(取得硬盘信息+网卡信息+key)key是自己约定好的一个字符串

但愿对你有帮助。
--------------------编程问答-------------------- 其实各种解决方案都有其优点和缺点,你需要做的尽量使用其优点,减少其缺点的暴露。
cookies的缺点是安全性、优点是在本地保存;既然你要能够减少用户登录的过程,本身就是降低了系统的安全性;
其次,在一些安全性较高的操作上保持数据的安全性就可以了,既目的性明确也减少对整个系统安全性的庞大分析。
比如:我登录网站是比较宽松的,要付钱的时候再次输入交易密码确保这个密码的安全性就好了。 --------------------编程问答-------------------- 如果要是一个登录后需要频繁交易操作的系统,
那么交易密码显然是不合适的,每次输入太繁琐,而且频繁输入密码的安全性也不高。不如丛登录严格把关下而不用交易密码。
反之则可以考虑简单增加个交易密码就完事。 --------------------编程问答--------------------
引用楼主 luck0235 的帖子:
当会员登录后在客户端生成COOKIE值:会员ID和KEY


呵呵,有的时候,一张图足以让一个概念混乱,还不如一句话明白。

你的这句话终于让我明白你的意思。不过,实际上,你在cookie中只要保存数据库中为本次用户登录所分配的passport记录的编号就可以了。passport记录中可以保存所对应的用户,以及本地登录有效期时间(例如在2分钟之后),以及最后访问时间(当用户刷新最后访问时间的时候我们可以推迟其有效期时间)。

在服务器端的应用程序要取得一个编号的passport记录,会首先从Cache中取,如果没有则才会读取数据库并且同时放入Cache中,这样就可以尽量减少访问数据库的次数。而放入Cache时,设置了缓存依赖项,使得的当数据库的passport改变时此Cache自动过期。

因此,cookie中没有必要保存那么多登录信息,仅仅需要保存一个long型数字即可。 --------------------编程问答--------------------
引用 16 楼 brood108 的回复:
首先,你这样做,用不用key,安全级别是完全一样的。 

不管是通过何种方式,我只要能搞到别人电脑上的cookie, 
就是说得到id跟key对应的cookie值,那么我就可以丛任何地方来用该cookie来跳过登录直接访问你的系统了。 

其次,要解决这个问题,我给你提供一下我们公司目前的解决方案把。 
1,客户端存一个简单的cookie,存放加密后的id就够用了。 
2,需要自动登录的用户,需要安装一个activex插件,安装成功后,取得用…


这有可能是形同虚设。如果一个人能够监听到cookie,他同时就监听到你的activex插件向服务器传递的电脑标识号,收集起来留下来备用了。如果一个人可以伪造提交的cookie,它就同样地可以通过通讯手段传递一个合法的电脑标识号,而此时它的电脑根本不用安装你的这个ActiveX插件。 --------------------编程问答-------------------- 我们也可以做一个ActiveX,反正ActiveX就是可以劫持用户机器的,它可以专门用来监听用户访问特定url时的特定信息例如账户、密码、所谓的电脑标识号,然后传递到我们的服务器上。如果我们希望访问某个网站,让这个ActiveX使用别人的信息自动提交这个信息就可以了。

ActiveX只是因为用的少,才被容易误认为是“加密”的手段。实际上,它也是劫持、窃取用户登录信息的关键手段。

为什么在普通的互联网应用上ActiveX没有使用起来,就是因为许多人其实就是用一个合理的借口来哄骗和劫持用户,例如过去国内下载网站猖獗时就借口给你免费下载软件而散步了不少广告插件来劫持用户的电脑强行弹出广告。 --------------------编程问答-------------------- 这样好 --------------------编程问答-------------------- 有时对于分布式服务器,喜欢用memcached,将session存入一组服务器中,其他服务器再从中读取。

  近阶段,微软与推出了类似于memcached,用于分布式的,可以存入数据对象
http://www.cnblogs.com/Terrylee/archive/2008/11/20/Microsoft-Distributed-Cache-Velocity-Part1.html --------------------编程问答-------------------- 1、可靠的安全性只能由https来保证,其他的方法都不可靠,至少现在银行和所有的在线支付都是这么整的。
2、是否需要记住客户端?所有的支付网站貌似都没有这个功能,因为这个很容易开后门。要知道客户端的一切信息都是可以伪造的。
3、至于客户端密码输入的安全问题,有两种方法:a.自己实现软键盘。b.ActiveX
4、你的设计里面可能还有同步的问题。。。 --------------------编程问答-------------------- LZ这么强调安全问题,不是做银行系统吧?
引用 14 楼 wsg13793257207 的回复:
个人感觉还是加密,然后存cookie比较好,数据库中可以存在两个id,一个md5加密的。

加密也是个不错的选择! --------------------编程问答-------------------- 马克之 --------------------编程问答--------------------
引用 20 楼 sp1234 的回复:
如果一个人能够监听到cookie,他同时就监听到你的activex插件向服务器传递的电脑标识号,收集起来留下来备用了。如果一个人可以伪造提交的cookie,它就同样地可以通过通讯手段传递一个合法的电脑标识号,而此时它的电脑根本不用安装你的这个ActiveX插件。...

20楼,你对atx控件的高级运用不是很了解。
简单的atx控件当然也是形同虚设
在加密方面有很多技巧的。
比如参数中增加一个time字段,
加密串中的sign=md5(取得硬盘信息+网卡信息+timd+(1900年或者自己特定的一个年份-time)时间差换算成毫秒数+key)

这样每次加密出来的sign都是不一样的,验证通过的时候,同时记录一下最后一次验证成功的 time
同一个用户如果下一次验证的时候,time必须大于上一次登录时候time。
这样同一个time无法使用2次,所以投机的人自然就被挡在了门外。
--------------------编程问答--------------------
引用 21 楼 sp1234 的回复:
为什么在普通的互联网应用上ActiveX没有使用起来。。。


ActiveX在涉及到钱的地方,应用非常广泛啊,比如网上银行登录的时候没有用到atx控件的基本上找不到吧,
还有很多重要的销售系统比如游戏点卡销售系统等等,应用的太广泛了。 --------------------编程问答-------------------- 没有绝对的安全。

--------------------编程问答-------------------- 比如去除超时限制,让SESSION像COOKIE一样可以不存在超时呢。
--------------------------------------------------------
如果非要这样,那可以把Session存入数据库中 --------------------编程问答-------------------- 1、我相信任何的加密都有可能被解密,如果真的出现无法被解密的时候还有可能被仿造,所以不要相信加密能百分百的保证安全!

2、我还相信任何放在客户端的东西都是不安全的,所以放在客户端的Cookie肯定也是不安全的,Session是放在服务器端的东西,在客户端与服务器之间通讯的过程中只交换Session的ID,而这个ID是在建立Session的过程中由服务器动态分配的,所以如果在结束Session的时候正确的销毁了Session,那么Session就是安全的! --------------------编程问答-------------------- 路过,学习 --------------------编程问答--------------------
引用 27 楼 brood108 的回复:
20楼,你对atx控件的高级运用不是很了解。 
简单的atx控件当然也是形同虚设 
在加密方面有很多技巧的。 
比如参数中增加一个time字段, 
加密串中的sign=md5(取得硬盘信息+网卡信息+timd+(1900年或者自己特定的一个年份-time)时间差换算成毫秒数+key) 

这样每次加密出来的sign都是不一样的,验证通过的时候,同时记录一下最后一次验证成功的 time 
同一个用户如果下一次验证的时候,time必须大于上一次登录时候time。 
这样同一个time无法使用2次,所以投机的人自然就被挡在了门外。 


这并不是重点。我在那里只是举个例子。你所说的生成变动的sign多么高级,你是假设劫持客户机器的人不是实时截获和复制信息到另一台机器上(通过一个服务器做收集和中转控制),而是凭空制造一个ActiveX。

可以仔细看我21楼的描述,我不是在讨论一个产品具体技术,而是只是随便举个例子!例子中假设一个服务器实时收集你的1万个客户的当时的操作的sign,或者知道你的其它任意信息,那么当我现在想模拟一个用户的信息时,我可以随便拿出一个来保持我对他的假冒身份,至少服务器是真假难辨。就算我不去模拟sign计算,我也不去监视通信,我就看看你在某些特征的屏幕(例如有密码特征字段的屏幕)上通过键盘都输入了什么内容总是很容易的吧。

我回这个这个帖子的目的,只是说明所谓的加密cookie没有绝对的成果,首先不在客户端保存过多的、静态的信息,而仅仅保存一个long型的编码,就可以了。通讯方面,自有SSL等方式保证。而如果下载ActiveX,呵呵,小心引狼入室。 --------------------编程问答--------------------
引用 28 楼 brood108 的回复:
引用 21 楼 sp1234 的回复:
为什么在普通的互联网应用上ActiveX没有使用起来。。。 
 

ActiveX在涉及到钱的地方,应用非常广泛啊,比如网上银行登录的时候没有用到atx控件的基本上找不到吧, 
还有很多重要的销售系统比如游戏点卡销售系统等等,应用的太广泛了。

这种应用ActiveX不是重点,重点是证书和安全输入...因为这种场景中普遍使用硬件客户端证书载体(USB Key)和模拟键盘,所以目前只能用ActiveX来实现...ActiveX只是手段不是目的,并不表明其安全,只是无可奈何的选择...这也是B/S应用的弱点之一...

这种场景能够应用ActiveX是基于用户对服务方的信任,如果没有足够的信任度那将是系统的灾难...没有多少公司能做到像金融机构那样轻易获得用户的信任... --------------------编程问答-------------------- 我其实没有认真看到楼主所说的“加密”的需求。对于楼主的设计,已经有很多设计提到过只需要在cookie中保存一个简单的key就够了,而无需考虑在客户端进行“会员ID与key验证”的问题。
--------------------编程问答-------------------- 学习下 --------------------编程问答-------------------- 楼主的文章,它集中在讨论cookie中保存“会员ID和KEY”,然后在服务器端中再去验证提交的这两个是否一致。他假设仿冒者仿冒别人是只会仿冒“会员ID”而不会仿冒“Key”(即只懂在界面上录入用户编号而不会亲自动手写稍微底层一点的通讯程序)。其实对许多人来说自己动手使用WebRequest写提供客户端cookie能力的程序程序毕竟对一些人来说不是很复杂。所以,比较多的是在通讯方面使用SSL,以及尽量不要随便使用ActiveX、Applet等程序,来切断恶意程序的入侵途径,而一旦被入侵了对方完全可以仿冒得更像一些。

各位可以在你的asp.net程序页面上打印一下Session.SessionID。你会看到即使你重新启动网站(例如在两次访问服务器之间重新保存一下web.config文件,此时Session集合中的数据、应用程序的静态变量之类的就都丢失了),或者Session到期过期之后,再访问此页面,你会看到SessionID是不变的。这是因为SessionID本来就是保存在cookie中的,并不会随着Session的丢失而丢失,SessionID唯一地标记会话的编码。所以,你此时不但不用在客户端保存“会员ID”,而且也不用保存“KEY”,这个SessionID就代表了这个Key的作用,当客户端访问页面的时候从后台数据库程序来读出从SessionID与用户对象的对应关系就可以了(我说过,所有对数据库的读取操作都可以使用3、4条语句使用Cache来优化,所以在你需要真正持久化保存数据时不必担心读取数据库比读取内存慢的问题)。因此,如果在客户不彻底关闭浏览器窗口前要保存关于他操作的信息,实际上asp.net的SessionID已经完全提供了这个Key值,它不会随着Session的丢失而丢失或者改变,在整个一次会话中一直保持着。
--------------------编程问答-------------------- 其实,使用一个自定个的编码来取代SessionID,看起来更清晰可靠一些。

其实Cookie中除了一个编码,其他任何信息都可以转移到后台数据库中(通常,在后台会设置一个“过期时间字段”来自动删除记录)。这是一种比较基本的设计,我们设计“安全”的系统时可以从这个起点来扩展。等系统已经比较“安全了”,将来可以考虑把不需要考虑安全性并且非常简单的东西懒得在后台系统中设计时才使用cookie保存。 --------------------编程问答-------------------- 我是这样做的,  加一个新的ASP.NET页面
在登陆的时候提交一个表单,POST方式
对新的页面进行编码  然后得到需要的信息 --------------------编程问答-------------------- learn --------------------编程问答--------------------
引用 18 楼 brood108 的回复:
如果要是一个登录后需要频繁交易操作的系统,
那么交易密码显然是不合适的,每次输入太繁琐,而且频繁输入密码的安全性也不高。不如丛登录严格把关下而不用交易密码。
反之则可以考虑简单增加个交易密码就完事。

要你那么说淘宝交易岂不是多此一举了?要想足够安全还是使用ssl证书登录。即使证书被别人给窃走了,导入证书还需要密码和身份认证。 --------------------编程问答--------------------
引用 sp1234  的回复:
例子中假设一个服务器实时收集你的1万个客户的当时的操作的sign,或者知道你的其它任意信息,那么当我现在想模拟一个用户的信息时,我可以随便拿出一个来保持我对他的假冒身份,至少服务器是真假难辨。。。


to:sp1234 
我在27楼的回复已经说的很明白,验证成功后,需要记录本次成功的time的
你下次拿同一个包过去提交,一验证当前time跟最后一次成功登录的time一样,就通不过的,或者拿以前的旧包,一验证当前time比最后一次成功登录的time要早,也是通不过的。这有点类似于一次性密码的功效。
atx控件的作用仅仅提供了一个安全加密的作用,只是一般人根本没有这样用,是本人的独创,你也可以试着找一下这种方法是否有我还没有发觉的漏洞。

这样的设计在当时确实遇到一个问题,比如用户修改系统时间到2010年,登录成功后time就被记录成了最后登录2010年,如果用户在修改系统时间成正常时间在登录的话,当前时间总是早于上次成功登录时间就一直无法登录。
对于这个小问题,解决方法是:用服务器时间而不用本地时间,登录前用ajax获取服务器时间来做time。

--------------------编程问答-------------------- 回41楼的:
淘宝交易属于那种不频繁的交易,用交易密码显然没有问题。

我举个频繁交易的例子把:
比如联通的充值系统,后边有人拍着队在缴费,客服不停的在充值,总不能每次充值都输入一次交易密码把!
再举个例子,比如网吧游戏点卡销售系统,玩家排着队购买点卡,网管mm也总不能不厌其烦的一直重复输入那个交易密码把!

--------------------编程问答-------------------- 所以这些系统是在登录环节尽量做足了安全验证,在交易的时候而不使用交易密码。 --------------------编程问答-------------------- 关注! --------------------编程问答--------------------
引用 37 楼 sp1234 的回复:
或者Session到期过期之后,再访问此页面,你会看到SessionID是不变的。这是因为SessionID本来就是保存在cookie中的,并不会随着Session的丢失而丢失,SessionID唯一地标记会话的编码。


我前断时间仔细玩过session和cookie

sessionid是放在cookie中的,是放在临时cookie中,关于这个临时cookie我找了N久,没找到
哪位牛人找到可以跟我说说,谢谢了

用户只要第一次请求服务器,服务器就会分配一个sessionid给客户端的临时cookie,接下来的用户请求
就把这个cookie一起传给服务器,在类似hashtable中根据sessionid查找对印用户信息

但是这个sessionid有时候并不是固定不变的
各位可以试试,当你的在服务器端没有把数据存入session对象时,用户每次请求发到服务器的sessionid是不一样的

还有,据ms的说法,同时在线超过一定数量时,多个用户sessionid可能相同,也就是说,共享一个会话数据
要大天下大乱了 --------------------编程问答--------------------
引用 42 楼 brood108 的回复:
这有点类似于一次性密码的功效。

既然是一次性密码,那么下次又要重新登录的了。
但楼主的需求是“记住密码”,过期之前,下次可以继续使用。 --------------------编程问答--------------------
引用 46 楼 anncesky 的回复:
引用 37 楼 sp1234 的回复:
或者Session到期过期之后,再访问此页面,你会看到SessionID是不变的。这是因为SessionID本来就是保存在cookie中的,并不会随着Session的丢失而丢失,SessionID唯一地标记会话的编码。 
 

我前断时间仔细玩过session和cookie 

sessionid是放在cookie中的,是放在临时cookie中,关于这个临时cookie我找了N久,没找到 
哪位牛人找到可以跟我说说,谢谢了 

用户只要第一次请求服务器,服务器…


这个临时的cookie找不到,也就是说,LZ的方法安全性方面还比不上session
补充:.NET技术 ,  ASP.NET
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,