使用 token 不是还是要每次都需要从数据库加载用户信息么和传统 session 有什么区别?

2021-09-13 08:33:40 +08:00
 SystemLight
8149 次点击
所在节点    Java
48 条回复
xuanbg
2021-09-13 08:43:54 +08:00
没区别,楼主继续用 session 就行。反正无状态的 token 适用范围有限,需要鉴权的时候,token 也要改成有状态的才行。
lcy630409
2021-09-13 08:45:23 +08:00
个人理解
token 可以节约后端的兼容时间,用 token 代替 session 可以做到 网页、app 、微信公众号等公用一套接口即可。
还不用考虑用户浏览器是否禁 cookie 了。

token 看项目,大部分项目就是简单的把 token 当成 session 的另版,少部分是把 token 当做信息传输
THESDZ
2021-09-13 08:51:02 +08:00
个人见解:

要看 session 这个概念

如果是说之前的实现方式,那就是有状态的,跟随服务节点的,不利于多服务,多节点的场景.

而如果说是为了保存用户信息这一目的,或者行为,那 token 可以理解为新的实现方式.
skypyb
2021-09-13 08:53:31 +08:00
token 是令牌的意思, 这个明白吧。
web 领域中的 session 也是一个用户的令牌, 这个没问题吧。

so, 我寻思 session 不就是 token 么(一种实现)? 没看懂在讨论什么

如果说的是 JWT (json web token)这种实现方式,这个确实是无状态的。
当你见到有人用 JWT 的同时, 还通过这个 JWT 去查库 /查缓存从而获取信息, 那么你应该判定这个人是个傻逼。
chendy
2021-09-13 08:56:03 +08:00
其实 sessionId 就是一种 token,只是通过 token 获取 session 数据 的操作由 web 框架做,而且一般将 sessionId 保存在 cookie 里,session 数据保存在 web server 里
因为 session 保存在 web server 里,当有多个实例时,需要同步各节点的 session,或者把 session 保存在数据库里(比如 spring-session )
因为 sessoinId 保存在 cookie 里,所以当客户端不支持 cookie 机制时,这套东西就没法用了
也因为 sessionId 保存在 cookie 里,所以可以使用浏览器自己的安全机制,比如 http-only,same-site 等
还是因为 cookie,所以对于前端是透明的,不需要自己管理,发请求默认带着(可能有跨域问题)

> 如果一个前端页面包含多个请求,每个请求都需要鉴权数据库压力不是很大么
相当于每次请求多一次查询,必然走索引,压力不大

> 解决是不是可以用 redis 集群做信息缓存,但是这样和传统 session 操作方式不是类似么
用 redis 可以提高性能,还自带过期时间机制,emm,本来就是 token 拿 session,就是一样的,区别是谁做怎么做

> 所以说 token 和传统 session 优势是什么,token 概念上是无状态,但是不可能真的把用户所有信息都存上呀
可以在浏览器之外的环境使用,而且因为全部自己实现,一些操作更方便(比如检测 token 状态,废掉某些 token ),用 JWT 可以在 token 里带数据,但也会带来额外的复杂性,需要自行评估使用
chanchan
2021-09-13 09:00:07 +08:00
我觉得
session 就是服务端查内存中是否有对应 session 来区分客户端
token 就是服务端解密看 token 里面内容来区分客户端
jorneyr
2021-09-13 09:08:19 +08:00
本质上没什么区别,为了支持多端用户的请求有的 token 实现简单点,例如 90% 的需求使用 JWT 存储用户基本不变的信息就能够满足,不需要服务器间同步 session 信息 (集群模式下高并发时同步 session 的性能损耗不可忽视,而 token 一般不需要),有需要的时候再回查用户信息。
huijiewei
2021-09-13 09:11:13 +08:00
session 有并发限制
tedzhou1221
2021-09-13 09:11:51 +08:00
JWT 的登出,或者刷新新的 Token 的处理,废弃旧的 Token

这两个功能是需要有状态的。

如果还有更好的处理方式,各位大佬可以告诉我一声,我正在做这个功能。感谢
ospider
2021-09-13 09:12:51 +08:00
你这都是书本上的定义,这么说的话 Cookie 和 Session 也分不开。实际使用中的 Cookie,Session,Token 区别大概是:

- Cookie:在浏览器的 CookieJar 中存储信息,比如购物车等,每次 HTTP 请求强制携带;
- Session:通过存储在 CookieJar 中的小段信息作为 Token,在服务器中加载相关完整信息;
- Token:通过存储在浏览器 localStorage 中加密签名过的 Token (一般是 JWT ),在 HTTP Authorization Header 中可选发送,并在服务器汇总加载相关完整信息。
murmur
2021-09-13 09:12:53 +08:00
jwt token 长度必定是有限的,如果用户的数据复杂了,token 就存不下了

如果你就是 uid 和中文名,那 jwt token 是勾的
golangLover
2021-09-13 09:17:59 +08:00
@tedzhou1221 #9 你不如去 4 楼问问说有状态 jwt 是 sb 的人 @tedzhou1221 #9
quanqiubiannuan
2021-09-13 09:21:26 +08:00
为什么要拿 token 和 session 来比?
fkdog
2021-09-13 09:22:58 +08:00
token 和 web session 本身就是同一个东西, 区别只在于生命周期和存储位置不一样.
huang119412
2021-09-13 09:25:27 +08:00
http 中的 session 和 cookie 关联在一起的,由 web server 自动维护,不需要用户操作,所以 session 并不灵活。
pastgift
2021-09-13 09:31:23 +08:00
Session 一般指的是,通过在 Cookies 里保存的一个 SessionID 实现鉴别用户的处理方式
好处是对 Web 前端,也就是浏览器基本上是透明的,前端开发不用管

Token 一般指的是,登录成功后,通过 JWT 等方式把少量信息编码成一串字符串返回给客户端,客户端在请求时一般将其附带在 HTTP Header 上,供服务端鉴别用户的处理方式
好处是任何客户端都能方便处理,并且 JWT 方式客户端本身也能获取字段信息

> 使用 token,由于 token 存储的是少量信息,是不是每次都还需要在拦截器中验证并去数据库加载用户信息
> 如果一个前端页面包含多个请求,每个请求都需要鉴权数据库压力不是很大么
> 解决是不是可以用 redis 集群做信息缓存,但是这样和传统 session 操作方式不是类似么

是这样的,如果 Token 中保存的信息少到只有 Token ID,那和传统 Session 的唯一差别就在于是不是依赖 Cookies 了

> 所以说 token 和传统 session 优势是什么,token 概念上是无状态,但是不可能真的把用户所有信息都存上呀

没有必要严格按照概念、范式,要面对实际问题

我实践下来的感受是有状态的 Token 比严格的无状态 Token 更好用,主要还是用在服务器端作废 Token,用户权限变更需要及时生效之类的处理上。

此外,Token 附带的信息并不限定「用户信息」

比如,要实现客户端发生变化( IP 、UserAgent 等)后,强制退出的功能,可以在 Token 发行时将客户端相关信息 MD5 后加入 Token,后续收到 Token 之后拿 Token 中附带的客户端信息 MD5 值和本次请求实际的客户端信息 MD5 值进行比对,有变化就拒绝,从而加强一定安全性,且操作完全不经过数据库、Redis 等其他组件。

再比如,要实现服务器端升级后,要求所有用户重新登录(重新发行 Token ),那么同理,发行时把服务器端的版本号写入 Token,收到 Token 时进行比对,这同样不需要额外查询数据库、Redis 。

也可以实现按照业务的请求转发。
比如 VIP 用户可以在 Token 中写入 VIP 标记,那 API 网关就可以将此请求转发到不同的服务器 /集群上处理,也能避免 API 网关去直接去数据库查询业务数据。

其他的那种比较直观的,比如展示在页面上的用户昵称如果写入 Token,那前端可能就可以不用额外请求用户信息接口。但这些都不太重要
jiangboenoch
2021-09-13 09:39:35 +08:00
@skypyb #4 最近在学后台,如果不往 token 放状态,那做 token 过期和自动续期应该用什么方案呢?
MLeo
2021-09-13 09:44:10 +08:00
简述 Cookie 、Token 、JWT 、Session
https://ichochy.com/posts/20200825.html
liyunyang
2021-09-13 09:44:41 +08:00
@pastgift 学习了
skypyb
2021-09-13 09:58:49 +08:00
@jiangboenoch #37
当 Token 需要例如过期、自动续期这种功能时, 那他就应该是一个有状态的 token, 典型的比如用户登陆后标识此用户的令牌。
每个请求都根据 Token 去查库就行了,比如查 Redis 。
如果在 web 端使用的话放不放 Cookie 里随便,只是不放 Cookie 的话里就自己控制刷新咯。

像那种无状态的,也就是完全不经过 DB 那一层的,比如 JWT 这种。
他压根就不适合做用户令牌这种场景,也不知道是不是什么培训班灌输的思想钢印。
最适合 JWT 的场景是那种需要短时间获取权限的行为,比如 XX 时间内有效的下载、查看等这种接口。

硬是要用 JWT 来当用户令牌的话,那为了查这个令牌有没有被吊销掉,还是得每个接口都去查一次库。那你反正得查库,为啥不顺便查出用户信息?

所以说,如果只是用作用户标志的话, 那就是直接用一个全局不重复的字符串来当 token 就行了,每次请求查一次库。

最后再说一下。session 是会话,web 端的 token 就是这个会话的令牌, 无论是叫他 sessionId 也好,叫他 xxx-token 也罢,他都是一个东西。和他放在 Cookie 里还是 localStore 里没有任何关联。

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

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

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

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

© 2021 V2EX