鉴权(2)Session与Token | 青训营笔记

162 阅读4分钟

这是我参与「第三届青训营 -后端场」笔记创作活动的的第3篇笔记

之前说到:浏览器第一次访问时服务端会设置cookie,并将cookie与不同用户对应起来存储到服务端。而在服务端通常是以session的形式进行存储的。

session

session是会话的意思,浏览器第一次访问服务端时,服务端就会创建一次会话,在会话中保存标识该浏览器的信息。

session与cookie均由服务器端生成,但前者保存在服务端,后者保存在客户端。二者统一使用可以弥补http协议无状态的缺陷(之后要谈到的JWT是无状态的)。

session-cookie认证

  1. 创建。服务器在接受客户端首次访问时在服务器端创建session(可以将session保存在内存中,也可以保存在redis中),为该session生成一个唯一标识字符串,然后在响应头中种下这个唯一标识字符串。
  2. 签名。这一步通过秘钥对sid进行签名处理,避免客户端修改sid(非必需)
  3. 浏览器中收到请求响应的时候会解析响应头,然后将sid保存在本地cookie中,浏览器在下次http请求的 请求头中会带上该域名下的cookie信息。
  4. 服务器在接受客户端请求时会去解析请求头cookie中的sid,然后根据这个sid去找服务器端保存的该客户端的session,然后判断该请求是否合法。

用户登录认证

使用session-cookie做登录认证时,登录时存储session,退出登录时删除session,而其他的需要登录后才能操作的接口需要提前验证是否存在session,存在才能跳转页面,不存在则回到登录页面。

Token

基于Token的认证,是指将所有认证相关的信息在服务器端编码成一个Token,并由服务器签名,以确保不被篡改。Token本身是明文的。存在Token里的信息可以有比如user_id、权限列表、用户昵称一类的。这样服务器只要拿着token和token的签名,就可以直接验证用户的身份是否合法

基于Token的认证的主要标准是Json Web Token (JWT)

JWT资料还是比较多的,不再赘述,另外这个网站不错 JWT

JWT的无状态性

session本身存储在服务端,可以随时进行管理,但JWT一旦颁发便无法收回,这就无法实现在服务器端对用户请求进行管理——管理员没法统计多少个人登录了,一个人登录了多少次,登陆了什么设备;同时,也无法强行“踢”掉一个用户的登录——JWT一旦生成,在失效之前,总是有效的。如果实现一个token黑名单之类的功能,就等价于实现了Session机制,无状态带来的好处就无从谈起。

扩展

另外如果token中还有session id,就可以在服务器端实现基于Session的认证。因此,你可以将user id、session id、token过期时间等几个关键数据放到payload里——只放这几个,不放其他的数据,得到一个用来做Session认证的JWT。更进一步,如果你把JWT的规范稍微小改一下,比如payload不用JSON,而是更紧凑的格式;定死了签名算法,即可省略JWT的header了;最后再优化一下编码格式,就能得到一个你自己的token。

Token和session的区别

  1. session-cookie的缺点:

    • 认证方式局限于在浏览器中使用,cookie是浏览器端的机制,如果在app端就无法使用cookie。
    • 为了满足全局一致性,一般会把session存储在redis中做持久化,而在分布式环境下,可能需要在每个服务器上都备份,占用了大量的存储空间。
    • 在不是https协议下使用cookie,容易受到CSRF跨站点请求伪造攻击。
  2. token的缺点:

    • 加密解密消耗使得token认证比session-cookie更消耗性能。
    • token比sessionID大,更占带宽。
  3. 两者对比

    • token认证不局限于cookie,这样就使得这种认证方式可以支持多种客户端,而不仅是浏览器。且不受同源策略的影响。
    • 不使用cookie就可以规避CSRF攻击。
    • token不需要存储,token中已包含了用户信息,服务器端变成无状态,服务器端只需要根据定义的规则校验这个token是否合法就行。这也使得token的可扩展性更强。

参考文章:

两种认证

前端鉴权(Cookie/Session、Token和OAuth)

\