基于 session 和基于 token 的用户认证方式到底该如何选择?

2016-05-04 11:22:13 +08:00
 qurioust

现在貌似大多数网站用户认证都是基于 session 的,即在服务端生成用户相关的 session 数据,而发给客户端 sesssion_id 存放到 cookie 中,这样用客户端请求时带上 session_id 就可以验证服务器端是否存在 session 数据,以此完成用户认证。这种认证方式,可以更好的在服务端对会话进行控制,安全性比较高(session_id 随机),但是服务端需要存储 session 数据(如内存或数据库),这样无疑增加维护成本和减弱可扩展性(多台服务器)。 CSRF 攻击一般基于 cookie 。另外,如果是原生 app 使用这种服务接口,又因为没有浏览器 cookie 功能,所以接入会相对麻烦。

基于 token 的用户认证是一种服务端无状态的认证方式,服务端不用存放 token 数据。用户验证后,服务端生成一个 token(hash 或 encrypt)发给客户端,客户端可以放到 cookie 或 localStorage 中,每次请求时在 Header 中带上 token ,服务端收到 token 通过验证后即可确认用户身份。这种方式相对 cookie 的认证方式就简单一些,服务端不用存储认证数据,易维护扩展性强, token 存在 localStorage 可避免 CSRF , web 和 app 应用这用接口都比较简单。不过这种方式在加密或解密的时候会有一些性能开销(好像也不是很大),有些对称加密存在安全隐患(aes cbc 字节翻转攻击)。

假如现在我想做一个适用于 web 和 native app 的 api 服务,该如何选择认证方式?还有如果使用基于 token 的认证方式, token 的设计有没有什么比较好的解决方案?

32141 次点击
所在节点    程序员
43 条回复
murmur
2016-05-04 11:26:25 +08:00
这两个实际上不冲突 就算是基于 token 也可以在登录的时候访问你所有的子系统把上面的 session 激活了 oauth 一样可以 session
想不泄露只能 https 传输 session id 都被偷了那就没办法了
以前 ecshop 的 session 是绑了 ip 的 pc 端无所谓 移动端可能会有问题 我不知道跨信号区时 ip 会不会变
还有见过的 神级办公室 一个办公室 2 个接入商(大概是电信联通双接入?) 但是策略没配置好 自己没事切 ip 玩
neutrino
2016-05-04 11:26:53 +08:00
qurioust
2016-05-04 11:39:32 +08:00
@neutrino 我理解的 oauth2.0 一般都是给第三方授权使用的,本站的用户授权直接登录就好了吧?
shiji
2016-05-04 11:43:28 +08:00
外加:
http://security.stackexchange.com/questions/19676/token-based-authentication-securing-the-token

不过有 jwt 这种现成的,还是直接拿来用更安全一些
SmiteChow
2016-05-04 11:55:38 +08:00
为什么说 token 不需要存储?
jimrok
2016-05-04 12:03:50 +08:00
token 的方式更适合 api 使用,原理上和 session 使用的 cookie 没有太大的差别,但 token 更加简单, token 可以从后端应用发放。而 session 的 cookie 必须在 web 层产生和发放。
hxsf
2016-05-04 12:18:34 +08:00
token 你也要存的 原理和 session+cookies 一样的。
orvice
2016-05-04 12:18:43 +08:00
@SmiteChow 如果用 jwt 不需要存。

如果写的接口 app 也用就用 token 吧,原理其实搜差不多。
chaegumi
2016-05-04 12:24:59 +08:00
最近刚搞好了 jasig cas
tabris17
2016-05-04 12:25:43 +08:00
这两个有本质区别么?
bobuick
2016-05-04 12:28:53 +08:00
jwt.io JWT 这个方式很不错的呢。 简单易用
qurioust
2016-05-04 14:15:12 +08:00
@neutrino @shiji @bobuick jwt 确实是基于 token 认证的一种比较好的实现方法,而且是行业标准 rfc7519 ,可以通过解码确认用户身份,这个我之前不知道,学习了。
我看到的 token 实现方式有多种,主要参考了这个: http://security.stackexchange.com/questions/81756/session-authentication-vs-token-authentication
Niphor
2016-05-04 14:21:41 +08:00
想起最近 搭个 node 渲染服务,后台 java 同学非要来 token 认证来取数...

我是蛋疼的不要不要的,同一内网机子,还来 设备认证 + token 认证 + csrf...
guotie
2016-05-04 14:31:48 +08:00
用 jwt , token 不还是要保存?
CodingWorker
2016-05-04 14:37:57 +08:00
学到了
realpg
2016-05-04 14:39:00 +08:00
为啥只有我觉得 token 和 session 就是一回事……
token 不就是 sessionid 么……
julyclyde
2016-05-04 14:43:17 +08:00
@realpg session 一般是指有状态的。 token 只是认证身份
GavinHao
2016-05-04 14:47:39 +08:00
jwt 的服务端实现是无状态的,在服务器端不需要保存 session 的,对于客户端而言倒类似于 session ID ,但不是去服务端找对应 session ,而是解码后校验。如有理解错误请指正。
realpg
2016-05-04 14:49:22 +08:00
@julyclyde
未必。而且 session 未必是 cookie 承载。现在已经没有人禁用 cookies 了,所以大家忘记了当年 session 的基本约定俗成规范是啥样的了。
说 token 是 session 的一种都不为过。不就是 sessionid=xxx 变成了 token=xxx 么

如果你写 java 版客户端,比如类似 android 客户端,使用 session 比使用 token 更省事,我指的 cookie 实现的 session , httpclient 之类直接外挂个储存的 cookiejar ,代码比 token 处处需要动传输数据结构更干净,而且可以实现 HEAD ,这对于 post/get 字串的方式来说,对于高性能系统优势明显
julyclyde
2016-05-04 14:55:33 +08:00
@realpg 我也没说 session 是 cookie 承载啊,你这不是竖个靶子自己打么; java 派似乎更偏好 querystring 承载。

状态的“内容”是保存在服务器端的,提供服务器端使用 session 数组读出内容的能力。 token 是 不承诺 提供这个的

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/276207

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX