[求解] 这样分配Session钥匙安全么? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
raincious
V2EX    PHP

[求解] 这样分配Session钥匙安全么?

  •  
  •   raincious 2013-12-08 22:27:54 +08:00 4544 次点击
    这是一个创建于 4326 天前的主题,其中的信息可能已经有所发展或是发生改变。
    好吧,我知道老是来这求解有点厚颜无耻,但是为了避免犯错,那么还是厚颜无耻一把好了。谢谢大家赐教。

    问题是这样的:如何保证Session是安全且不可伪造的。因为之后为了节省查询数,我想直接在数据库会话上绑定用户的数据,拿到这个Key就相当于得到了用户权限。

    [我现在的做法是,Session只作为记录客户活动状况的东西,只有createTime、updateTime和requests这几个字段,用户对应的权限使用另一套Ticket系统来实现。那套系统会给客户端颁发由用户ID和一串随机码组成的凭证来确认用户。但这就意味着多至少一次查询,而且我的架构为了速度和多数据库还支持各种JOIN。]

    我想出的新方案是这样的:

    (1)通过将IP地址加入SessionKey的运算条件(整个要素由 IP + 两组随机数 + HTTP_USER_AGENT 组成),然后用MD5输出一段Hash作为Cookie的钥匙来实现。因为MD5快而且定长,这样数据表就好设计了。

    (2)这样输出了一段SessionKey,然后再用用户的IP + 这个SessionKey来Hash出另一段SessionVerifyKey。之后将这两个Key组合好发送给客户端(65个字符长)。

    (3)下次读出的时候,用返回的SessionKey + 用户的IP产生的Hash比对这个返回的SessionVerifyKey,如果一致就认为是合法的Session,否则就重新产生一个。

    实现的代码在这里:
    https://github.com/raincious/facula/blob/master/libraries/units/class.session.php#L231

    但问题是,MD5现在的碰撞率太高了,这样能否保证Session的钥匙无法被撞开呢?或者我最好还是守着旧方法就好了?

    而且我看了V2EX的Cookie,其中的auth应该就是Session钥匙,但貌似也只有一个Hash串呢?或者这样就足够安全了?
    21 条回复    1970-01-01 08:00:00 +08:00
    icanc
        1
    icanc  
       2013-12-08 22:51:40 +08:00   1
    如果没有大量用户,谈不上碰撞。如果真的有人想碰撞,楼主考虑的应该是如何应付CC攻击了。
    ejin
        2
    ejin  
       2013-12-08 23:15:37 +08:00
    什么叫md5碰撞率太高了啊 你不会把它伪装成sha1么,伪装成其他样子的么,md5是16位你就一定要坚持16位?只要别人没办法拿到你的源码,谁知道你的是什么算法,或者根本就是你自己的算法?

    明明是sha1你可以伪装成md5,md5也可以伪装成sha1,这又不是什么难的,非要告诉别人你是什么什么什么算法,通过什么什么什么来计算出这个值,你这不是自己找不自在么

    要想碰撞,那也要知道你是什么算法才行啊
    ejin
        3
    ejin  
       2013-12-08 23:17:41 +08:00   1
    哦哦 你是怕用户多了碰撞?那你加入几位随机码进去,要想碰撞没有个几亿年怕是不可能了哦,什么?几亿年后还有人上你……哦不是,是上你的网站?我觉得你想太多了
    dongbeta
        4
    dongbeta  
       2013-12-08 23:20:47 +08:00   1
    楼主想多了
    Livid
        5
    Livid  
    MOD
    PRO
       2013-12-08 23:21:25 +08:00   1
    用户数量到几万这个量级的时候,SHA1 也是会碰撞的。
    bigcoon
        6
    bigcoon  
       2013-12-08 23:49:13 +08:00
    没有用户id么?
    txlty
        7
    txlty  
       2013-12-08 23:52:57 +08:00
    没太看明白。我在用户验证环节 不用session。
    把user & md5('pass'.'xxx') & 登陆时的随机码 连成一个字段,用康盛的authcode函数加密一下,存进客户端cookie [usr]字段。这个usr就包含用户登录所需的全部信息。
    用户名、md5密文、随机码 在登录成功后全部缓进memcache。以后直接比对缓存即可。
    这样能破不?
    9hills
        8
    9hills  
       2013-12-09 00:00:02 +08:00   1
    碰撞几率是能算出来的,任意两个MD5的碰撞几率是 1/(2^64)

    如@Livid 所说在几万的数量级连SHA1也会发生碰撞现象有点不可思议,求实例(两个SHA1一样的字符串)
    raincious
        9
    raincious  
    OP
       2013-12-09 00:00:51 +08:00
    @bigcoon 是的,这也是为啥当初要做个Ticket用来辅助。

    Session实现的方案当初只是为了在浏览器和网站之间实现唯一性识别做的。当然,如果能唯一识别了,绑定个用户在上面也应该没什么问题吧理论上。


    @txlty

    抱歉,我自己的规范是不允许以任何形式把用户的密码发回去。无论是怎么Hash或者加密的。
    kingwkb
        10
    kingwkb  
       2013-12-09 00:01:38 +08:00 via Android
    @Livid session id碰撞有好的解决办法么
    raincious
        11
    raincious  
    OP
       2013-12-09 00:06:38 +08:00
    @Livid @9hills 哈。我倒是想通了。这个架构目标支持的最大同时在线数(Session表里面最多)也就5000同时在线吧到顶。考虑到产生的数据都是临时的,这个碰到的概率太小了。

    所以如果用户的Cookie不失窃的话,理论不太可能出现问题了。所以我就决定暂时先这么办嗯。

    不过我现在倒是担心如果Cookie失窃的话这个机制是不是能继续保证用户数据安全了(如果盗窃方拿不到IP地址的话)。
    9hills
        12
    9hills  
       2013-12-09 00:07:45 +08:00   1
    @raincious 其实用secure_cookie(里面存用户ID)+ redis/memcache(存server side session)的性能也挺好

    放客户端就麻烦多了,安全性各种考虑
    raincious
        13
    raincious  
    OP
       2013-12-09 00:15:17 +08:00
    @9hills 嗯,倒是。但是这牵扯到另一个问题:我懒。不想未来要给框架维护那么多服务器。

    而且我现在只是在设计接口,所以目前这套东西最后的最后只是丢出一个合法的SessionKey给用框架的家伙注册的函数,剩下的他自己解决了(想要读数据库什么的随便嗯)。我自己保证架构什么的越简单越好。

    反正就我自己的测试这样的设计。。。还算凑合吧,只要这样注册下,未来调用很方便嗯。。。
    https://gist.github.com/raincious/7859598
    9hills
        14
    9hills  
       2013-12-09 00:15:23 +08:00   1
    @raincious cookie可以参考下Tornado的Secure Cookie,只要server那段的secure key不泄漏,cookie是无法伪造的

    但是失窃么,所以用全程HTTPS吧,这样只能在client端窃取(client端被攻陷神仙也防不住)
    raincious
        15
    raincious  
    OP
       2013-12-09 00:22:39 +08:00
    @9hills 好的。我去看看。谢谢建议嗯。
    crny520
        16
    crny520  
       2013-12-09 08:56:25 +08:00
    @raincious 这是PHP5.4还是5.3新增的语言?
    raincious
        17
    raincious  
    OP
       2013-12-09 09:34:17 +08:00
    @crny520 是啊,用到了5.3的匿名函数:http://www.php.net/manual/en/functions.anonymous.php
    est
        18
    est  
       2013-12-09 11:11:01 +08:00
    担心md5碰撞就是地命海心。

    王小云的那个思路做出来的结果也只能是2个不同长度的字符串得到相同md5。还飞jb长。还是non-ascii 不可打印的字符为主。

    如果散列有那么容易碰撞,那就不叫散列了。那个叫车祸现场列。
    raincious
        19
    raincious  
    OP
       2013-12-09 11:47:06 +08:00
    @est 但是为了安全还是地命海心吧。程序质量更高,就不用担心过一段时间得重构什么的了。而且这样折腾下来速度也不会变慢很多。

    MD5这东西看似安全,但概率问题还是说不定的,我自己就在搜狐社区(不过是很多年前了)和优库(去年)的时候撞到了别人的Session里。所以感觉这方面还是小心为妙。
    est
        20
    est  
       2013-12-09 14:01:15 +08:00
    @raincious 这个session串用户了,确定和md5碰撞有关?
    raincious
        21
    raincious  
    OP
       2013-12-09 15:14:22 +08:00
    @est 不完全确定,但是清理掉了Cookie就解脱了。所以猜测是这样罢了。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     932 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 24ms UTC 18:45 PVG 02:45 LAX 11:45 JFK 14:45
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86