服务端一般怎么处理 token?

2017-04-01 11:49:37 +08:00
 AscenZ

之前一直在写 iOS ,前后端分离,每次请求带上 token 就行了。

现在想写一下后端,想问一下一般是怎么处理 token 的?

用户登录的时候根据 userID 加上时间戳 或者 加上一个自定义值 用加密算法生成 token 之后,

1.存到数据库中(能设置过期时间吗?),每次客户端请求的时候取出来验证

2.存到 redis 中,设置过期时间,每次客户端请求的时候取出来验证

3.不存,每次客户端请求的时候根据之前的生成方法再生成一次来验证

哪种方法成本更低? 或者有更好的方法吗?

11428 次点击
所在节点    程序员
38 条回复
sfwn
2017-04-01 11:54:20 +08:00
第三种能解释下吗
chuanwu
2017-04-01 12:03:11 +08:00
@sfwn 猜测应该是类似 jwt 那种吧。
AscenZ
2017-04-01 12:10:09 +08:00
@sfwn
例如客户端登录后服务器生成 token 之后返回,之后客户端请求的时候带上这个 token ,服务端每次都根据之前生成的方法(例如加上了自定义值,使用了什么加密算法)再生成一次来比较,一样就验证成功
就是楼上说的 JWT ,我也是刚接触
horsley
2017-04-01 12:18:51 +08:00
我实现过的是不存,仅验证
lurenw
2017-04-01 12:22:33 +08:00
有的数据库是支持设置过期时间的, 1 和 2 一个意思。
ytmsdy
2017-04-01 12:23:03 +08:00
一般都是 token+用户名,在数据库中查询 token 对应的用户名。
如果用户名和客户端发送的一致则继续正常的访问。
如果不一致丢 401 错误。
jedrek
2017-04-01 12:36:10 +08:00
都不需要存,对用户 ID 和过期时间戳签名即可得到 token 。
token 不应存私密的信息,所以不需要加密。而是要签名,防篡改。
klesh
2017-04-01 12:40:13 +08:00
看 jwt 规范你就明白了。
一般不需要存,但若要实现 revoke 之类就要存储
jedrek
2017-04-01 12:46:33 +08:00
@klesh 比如修改密码后,需要吊销之前的 token ,所以用户 ID 和过期时间戳之外,再加一个值,这个值可存在缓存中,每次请求先对 token 验证,通过后再拿缓存中的值与 token 中的比较
byfar
2017-04-01 12:47:14 +08:00
登录成功后生成一个 token 存表存 redis 都行

一个 token 对应一个 uid
avichen
2017-04-01 13:23:06 +08:00
JWT : Json web Token ,可以去了解一下
klesh
2017-04-01 13:49:42 +08:00
@jedrek

这样的流程需要进行, 1 。解码 token , 2 。验证 token , 3 。把值与缓存比对。
我认为不需要所谓的“值”,直接把 token 放到缓存中,利用 set 进行比对是很快的,都不需要解码和验证 token 。同时, token 一定要设定有效期,如一周,这样缓存中只需存最近一周内被 revoke 的 token ,在空间和时间上更合理。如果用户不喜欢每七天登录一次,可以在客户端设计一套自动 refresh token 的机制。
Ouyangan
2017-04-01 14:02:16 +08:00
直接用 session 吧 ,自己搞来搞去最后都搞成了 session
sampeng
2017-04-01 14:11:26 +08:00
一直很不理解 token 的使用场景。。。搞来搞去不就是个 session 么?
完整实现了 http 协议的哪个不能支持 session ?还是因为懒
SourceMan
2017-04-01 14:14:16 +08:00
2
jimzhong
2017-04-01 14:15:19 +08:00
@sampeng 主要是因为 session 依赖于 cookie 吧
jedrek
2017-04-01 14:26:42 +08:00
不用 JWT , token 是这样的结构:签名后的字符串-用户 ID-指纹,共三段,每段中划线分隔.由于要谈到 token 吊销需要存储的问题,所以这里可以不需要存时间戳了。

当注册 /登录成功后:
1. 指定一个指纹,任意值都可以,只要这个值对这个用户没有使用过即可。
2. 将指纹和用户 ID 拼起来并签名,组成 签名后的字符串-用户 ID-指纹 这样结构的 token 。
3. 将用户 ID 与指纹对应起来放到缓存中,并且设置缓存过期时间,这个时间就是 token 有效期。
4. 将 token 返回给客户端。

当用户再次请求时:
1. 将 token 中的用户 ID 和指纹再签名(通过服务端私钥),比对提交的 token 签名后的字符串 就可将篡改或伪造的 token 过滤掉了(或许这一步有更好的实现方式)。
2. 过了上一步,仍然无法确定 token 是否已被吊销。获取缓存中的指纹与提交的 token 的指纹比对,若缓存中取不到指纹值(缓存已设置过有效期期)或缓存中的指纹与 token 的指纹值不相符,就说明这个 token 被吊销了。
3. 通过了上面两步,表示这个请求是已认证了的。
jedrek
2017-04-01 14:27:23 +08:00
@klesh 忘了
jarlyyn
2017-04-01 14:29:48 +08:00
我是做了一个 cachegroup.
前端 redis 热数据,后端 mysql 全部数据。

另外, token 不是应该随机生成的吗?
ppmoon
2017-04-01 14:31:45 +08:00
推荐楼上说的 JWT ,这种方式比较简单,如果应用安全级别不高很实用。客户端存一份 token ,存哪里都行,然后每次需要权限操作的时候就带着 token 去请求。后端接到请求的时候就验证一下。 JWT 把状态放在客户端,后台压力小,要是使用 session 还需要占用服务器资源。 session 多了还需要去管理 session

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

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

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

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

© 2021 V2EX