本人菜鸟,目前在开发几个 RESTFul API 。现在遇见一个头疼的问题,希望大家不吝指教:
实际的业务流程是:
用户名
和密码
去签定身份Authorization
Header 中带着这个 Token目前采用的方案是:
问题和纠结是:
感谢大家的回复!
目前主要纠结的还是Json Web Token
既然不建议保存在服务器,那么服务器又怎么能保证同一时间段只能为一个用户维护一个Token呢?
1
Clarencep 2016-11-15 17:18:37 +08:00
“但是如果用户写好的某个调用程序正在执行,不小心又重新生成了一个 Token ,那么调用就会停止。” -- 这种情况一般不需要考虑, 可以参考下各大开发平台的 API (如微信和支付宝)。
|
2
mynameisny OP @Clarencep 哦哦哦。了解了,这种属于应该操作失误吧。不知纠结一是不是可以给些指点?想保证唯一 Token ,应该怎样搞……
|
3
ty89 2016-11-15 17:32:39 +08:00
看你正文里面写到,“ token 保存在 Redis 中,以用户名作为 Key “,这样的话如果你的生成 token 的算法没毛病,就可以认为是唯一的了。不知道你纠结的点在哪里。
|
4
ty89 2016-11-15 17:34:55 +08:00
至于第二点,你担心得完全多余了。
|
5
mynameisny OP @ty89 纠结之处在于好多资料上说, JWT 生成 Token 是不应该放在服务器端保存起来的,但是不记录它的状态怎么能知道它只有一份呢?
|
6
xxxyyy 2016-11-15 17:47:14 +08:00 via Android
你反过来做就行了,只保存吊销的 token ,在鉴权时查看下 token 是否在 redis 中,如果在就拒绝就可以了,在保存到 redis 的 token 还可以设置一个 ttl ,时间是 token 的过期时间,这样就不需要手动去清理 redis 里的 token 了。
|
7
mynameisny OP @xxxyyy 感谢回复,我现在就是这么做的呢,依赖于 Redis 的 TTL ,过期了就会把那个 Token 自动的删除,如果 Token 不存在了就不准调用。关键的问题还是这个 Token 要保存的问题,是不是我的这个情景里是必须要在服务器保持一份 Token 呢?
|
8
xxxyyy 2016-11-15 17:54:05 +08:00 via Android
@mynameisny 为什么要保存 token ?
|
9
Herobs 2016-11-15 17:56:48 +08:00 via Android
token 本身就携带了足够多的信息,包括过期时间。泄漏的话,只会是在有效期内存在风险,这个是可以接受的。
把 token 存起来是完全没有意义的, JWT 就是用来去中心化,达到 stateless 的目的。 |
10
mynameisny OP @xxxyyy 是希望保证让一个用户在一段时间内只有一个 Token 是有效的。
|
11
mcfog 2016-11-15 18:00:55 +08:00
简单研究过 jwt 。个人不建议用 jwt 作 session 用途。原因基本和你的纠结一样, jwt 最大的好处就是把数据带到前端去转了一圈,从而能实现无状态服务端,但 session 这件事天生就是关于维持状态的,和 jwt 是矛盾的。有状态的服务直接发 uuid 作 session key 就好
另外 jwt 之前很多开源实现暴露过致命漏洞(客户端可以直接构造加密方式为不加密的 token 通过校验)这也让我对 jwt 的影响分大减,说白了 jwt 就是参数头+body 的一个约定而已,和自己定协议唯一的区别就是他开源,有三方库,但这些库的质量如果没保证的话,还不如自己定协议靠谱。毕竟自己写代码出 bug 那是自己水平不够测试不严,用三方库出 bug 那完全是吃苍蝇 建议阅读: http://cryto.net/~joepie91/blog/2016/06/13/stop-using-jwt-for-sessions/ https://auth0.com/blog/critical-vulnerabilities-in-json-web-token-libraries/ |
12
mynameisny OP @Herobs 对对,我就是看到了很多关于 JWT stateless 方面的介绍才来求助的。如果不考虑泄漏的情况,只是不希望用户有多个 Token 同时可用,是不是我现在的这个问题就限制在必须是有一个“中心”了呢?
|
13
Herobs 2016-11-15 18:06:03 +08:00 via Android
@mynameisny 不希望用户有多个 token 同时有效的目的是什么,如果非要达到这个目的,可以考虑为每个用户维护一个递增的整数,来达到节省资源的目的。
|
14
xxxyyy 2016-11-15 18:08:23 +08:00 via Android
要保证让一个用户在一段时间内只有一个 Token 是有效,这就产生状态了,需要服务器端保存这个状态才行。
|
15
mynameisny OP @mcfog 受教受教!! JWT 和 Session 关于状态果真是矛盾的。其实我现在的方案中是在借用了 JWT 生成 Token 的功能而已,完全没有使用它无状态的特性。我只是享受到了一个确定草案的开源实现而已……如您所言,我完成可以自己实现一个约定,能解密调用者传递来的 Token ,解析出我想要信息,并保证 Token 唯一就可以了。
|
16
mynameisny OP @xxxyyy 是是是,感谢众高手们的指点,是我误用 JWT 了,我确实是需要带“状态”的 Token 。
|
17
ctsed 2016-11-15 18:59:20 +08:00 via iPhone
我打开俩帖子,第一个帖子需要刷新一下才能回复?
|
18
caixiexin 2016-11-15 19:04:32 +08:00 via Android
用 jwt 做认证的话,不需要在服务的保存它,这有篇文章讲的挺清楚的。
http://blog.leapoahead.com/2015/09/07/user-authentication-with-jwt/ |
19
Koyoter 2016-11-15 19:17:24 +08:00
token 绑定 ip 或者 mac 地址?变了就算下线
|
20
mynameisny OP @caixiexin mcfog 11 楼和 xxxyyy 14 楼的回复是很精僻的, Token 本身是不需要状态的,但是限定了它在一段时间只有唯一实例,就是产生状态了,一旦产生了状态了就成了“ SESSION ”
|
21
mynameisny OP @Koyoter 可能是误解了,并不是讨论 Token 绑定用户的问题,同一用户同一 IP 同一 MAC ,在同一时刻生成了多个有效 Token 。
|
22
future0906 2016-11-15 22:32:34 +08:00
@mynameisny
我没有用过 JWT ,但是我猜应该是类似于 signed-json 的东西,这个和 token 本质上是有区别的,用来做简单的鉴权可以,真正做 API 的话必须保存一个 token=>auth_state_dict 的一个关系。这个好处是服务端可以控制这个鉴权的信息(权限变更之类的) 你关键的问题在于对 RESTFul 对 stateless 的误解,所谓的 stateless 是对 HTTP 层来说的,对于 HTTP 后面的资源根本没有办法做到 stateless (不然怎么保存用户数据?)。 所以传统意义的 session ( http 层)肯定不能用,只能是存在数据库中,以保证服务可以 fail-over 。 |
23
mynameisny OP @future0906 您提到的“ stateless 是对 HTTP 层来说的”这点理解了,但是不能将这个 Token 放在 session 中实现 fail-over 这块还是不怎么明白,烦请再帮忙讲一下。
可不可以只在用户的 SESSION 作用域中保存一份唯一的 Token ,再次请求 Token 的时候就生成并覆盖 SESSION 中这个 Token 。同时保证每次拦截认证都是从 SESSION 获取这个唯一 Token ? |