之前一直在写 iOS ,前后端分离,每次请求带上 token 就行了。
现在想写一下后端,想问一下一般是怎么处理 token 的?
用户登录的时候根据 userID 加上时间戳 或者 加上一个自定义值 用加密算法生成 token 之后,
1.存到数据库中(能设置过期时间吗?),每次客户端请求的时候取出来验证
2.存到 redis 中,设置过期时间,每次客户端请求的时候取出来验证
3.不存,每次客户端请求的时候根据之前的生成方法再生成一次来验证
哪种方法成本更低? 或者有更好的方法吗?
1
sfwn 2017-04-01 11:54:20 +08:00
第三种能解释下吗
|
3
AscenZ OP @sfwn
例如客户端登录后服务器生成 token 之后返回,之后客户端请求的时候带上这个 token ,服务端每次都根据之前生成的方法(例如加上了自定义值,使用了什么加密算法)再生成一次来比较,一样就验证成功 就是楼上说的 JWT ,我也是刚接触 |
4
horsley 2017-04-01 12:18:51 +08:00
我实现过的是不存,仅验证
|
5
lurenw 2017-04-01 12:22:33 +08:00
有的数据库是支持设置过期时间的, 1 和 2 一个意思。
|
6
ytmsdy 2017-04-01 12:23:03 +08:00
一般都是 token+用户名,在数据库中查询 token 对应的用户名。
如果用户名和客户端发送的一致则继续正常的访问。 如果不一致丢 401 错误。 |
7
jedrek 2017-04-01 12:36:10 +08:00 1
都不需要存,对用户 ID 和过期时间戳签名即可得到 token 。
token 不应存私密的信息,所以不需要加密。而是要签名,防篡改。 |
8
klesh 2017-04-01 12:40:13 +08:00 via Android 1
看 jwt 规范你就明白了。
一般不需要存,但若要实现 revoke 之类就要存储 |
9
jedrek 2017-04-01 12:46:33 +08:00 1
@klesh 比如修改密码后,需要吊销之前的 token ,所以用户 ID 和过期时间戳之外,再加一个值,这个值可存在缓存中,每次请求先对 token 验证,通过后再拿缓存中的值与 token 中的比较
|
10
byfar 2017-04-01 12:47:14 +08:00
登录成功后生成一个 token 存表存 redis 都行
一个 token 对应一个 uid |
11
avichen 2017-04-01 13:23:06 +08:00
JWT : Json web Token ,可以去了解一下
|
12
klesh 2017-04-01 13:49:42 +08:00 1
@jedrek
这样的流程需要进行, 1 。解码 token , 2 。验证 token , 3 。把值与缓存比对。 我认为不需要所谓的“值”,直接把 token 放到缓存中,利用 set 进行比对是很快的,都不需要解码和验证 token 。同时, token 一定要设定有效期,如一周,这样缓存中只需存最近一周内被 revoke 的 token ,在空间和时间上更合理。如果用户不喜欢每七天登录一次,可以在客户端设计一套自动 refresh token 的机制。 |
13
Ouyangan 2017-04-01 14:02:16 +08:00
直接用 session 吧 ,自己搞来搞去最后都搞成了 session
|
14
sampeng 2017-04-01 14:11:26 +08:00
一直很不理解 token 的使用场景。。。搞来搞去不就是个 session 么?
完整实现了 http 协议的哪个不能支持 session ?还是因为懒 |
15
SourceMan 2017-04-01 14:14:16 +08:00
2
|
17
jedrek 2017-04-01 14:26:42 +08:00 1
不用 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. 通过了上面两步,表示这个请求是已认证了的。 |
19
jarlyyn 2017-04-01 14:29:48 +08:00
我是做了一个 cachegroup.
前端 redis 热数据,后端 mysql 全部数据。 另外, token 不是应该随机生成的吗? |
20
ppmoon 2017-04-01 14:31:45 +08:00 1
推荐楼上说的 JWT ,这种方式比较简单,如果应用安全级别不高很实用。客户端存一份 token ,存哪里都行,然后每次需要权限操作的时候就带着 token 去请求。后端接到请求的时候就验证一下。 JWT 把状态放在客户端,后台压力小,要是使用 session 还需要占用服务器资源。 session 多了还需要去管理 session
|
21
jarlyyn 2017-04-01 14:34:10 +08:00
|
22
kulove 2017-04-01 14:35:37 +08:00
aes 加密用户 id ,过期时间 每次请求解密判断是否过期
|
23
phx13ye 2017-04-01 15:00:38 +08:00
如果 jwt 也要存,不就变成 session 了么,后续又会遇到一对分布式 session 要处理的问题,这样好处在哪?求详细说明
|
25
phx13ye 2017-04-01 16:18:23 +08:00
@avichen 想把 JWT 作为 app 端和网页端登录凭证。那么 logout 的时候,一般也只是客户端删掉 JWT 吗?
假如在 payload 里设置过期时间 60 秒,如何防止在 59 秒还可以成功请求, 61 秒就要求用户重新登录的情况呢? JWT 有自带的机制去处理吗 |
26
vjnjc 2017-04-01 16:27:23 +08:00
1 , 2 看起来一样。 1 的话存的时候带过期时间呀。
3 的话看起来不安全,通过逻辑生成总是有漏洞(/规律) |
27
avichen 2017-04-01 16:30:02 +08:00 1
@phx13ye #25 logout 时可以采用你说的删除 token ,另外 59 秒的问题,貌似没有解决办法,这一秒请求完了,下一秒再请求,它不就过期了嘛,对你的业务影响会很大吗?
|
28
behappy 2017-04-01 17:07:13 +08:00
@jarlyyn
请教一个问题,假如我先打开网页 A ,这时候服务器在努力运算生成 token,但是出于某种原因卡住了。然后我又开了个新标签仍然打开网页 A, 然而这次服务端生成 token 后很快就返回了然后写入 cookie 成功了。然后前一次的 token 慢悠悠的返回了,把第二次的 token 覆盖掉了。这种情况该咋整 |
30
jarlyyn 2017-04-01 17:27:09 +08:00
|
31
CareiOS 2017-04-01 17:32:45 +08:00
@sfwn 就是服务器用对称加密,将数据加密得到一个 string ,然后返回给 client, 每次 client 请求都带上这个 string, 服务器收到后解密,判断是否过期等....
|
32
asen477 2017-04-01 17:47:41 +08:00
一般 app 端存 token 不会做短期的时间验证
一般存在本地都会很长时间。 |
36
phx13ye 2017-04-01 19:44:08 +08:00 via iPhone
@chuanwu 嗯,之前的做法是在记录一下心跳时间,导致服务端要记录。也许可以在快要过期时重新分配一个 token 更好
|
37
yankbytes 2017-04-02 01:57:57 +08:00 via iPhone
@behappy 再去拿个 token ?一般来说除了 accesstoken 还会有 refreshtoken
|
38
sutra 2017-04-02 13:23:41 +08:00
spring-session
|