JWT与Session的作用

Introduction

What’s Session

In computer science, in particular networking, a session is a temporary and interactive information interchange(交换) between two or more communicating devices, or between a computer and user (see login session).

sessions consist of three phases:

  1. The client establishes a TCP connection (or the appropriate connection if the transport layer is not TCP).
  2. The client sends its request, and waits for the answer.
  3. The server processes the request, sending back its answer, providing a status code and appropriate data.

As of HTTP/1.1, the connection is no longer closed after completing the third phase, and the client is now granted a further request: this means the second and third phases can now be performed any number of times.

Theory

当client通过用户名密码请求server并通过身份认证后,server就会生成身份认证相关的session数据,并且保存在内存或者内存数据库。并将对应的sesssion_id返回给client,client会把保存session_id(可以加密签名下防止篡改在cookie。

此后client的所有请求都会附带该session_id(毕竟默认会把cookie传给server),以确定server是否存在对应的session数据以及检验登录状态以及拥有什么权限,如果通过校验就该干嘛干嘛,否则重新登录。

对比JWT的优势:

  • 最大的优势就在于可以主动清除session了;
  • session保存在服务器端,相对较为安全;
  • 结合cookie使用,较为灵活,兼容性较好;

劣势:

  • cookie + session 在跨域场景表现并不好;
  • 如果是分布式部署,需要做多机共享session机制,实现方法可将session存储到数据库中或者redis中;
  • 基于cookie的机制很容易被CSRF;
  • 查询session信息可能会有数据库查询操作;
  • 服务之间依赖访问不好处理。每个服务需要有单独的cookies。

What’s JWT

JSON Web Token (JWT) is an open standard (RFC 7519) that defines a compact(契约) and self-contained way for securely transmitting information between parties as a JSON object. This information can be verified and trusted because it is digitally signed. JWTs can be signed using a secret (with the HMAC algorithm) or a public/private key pair using RSA or ECDSA.

if the token is sent in the Authorization header, Cross-Origin Resource Sharing (CORS) won’t be an issue as it doesn’t use cookies.

The following diagram shows how a JWT is obtained and used to access APIs or resources:

  1. The application or client requests authorization to the authorization server. This is performed through one of the different authorization flows. For example, a typical OpenID Connect compliant web application will go through the /oauth/authorize endpoint using the authorization code flow.
  2. When the authorization is granted, the authorization server returns an access token to the application.
  3. The application uses the access token to access a protected resource (like an API).

using it on HTTP Headers, Authorization: Bearer

对比Session的优势:

  • 可扩展性,方便服务进行扩展。
  • 安全性
  • RESTful API 服务

劣势:

  • 传输开销比 Session 大,特别是大量数据编码在JWT里面的时候。
  • 实效性,无状态JWT的实效性相比session太差,只有等到过期才可销毁,而session则可手动销毁。

JSON Web Token structure:

  • Header

    The header typically consists of two parts: the type of the token, which is JWT, and the signing algorithm being used, such as HMAC SHA256 or RSA

  • Payload

    The second part of the token is the payload, which contains the claims. Claims are statements about an entity (typically, the user) and additional data. There are three types of claims: registered, public, and private claims.

  • Signature

    To create the signature part you have to take the encoded header, the encoded payload, a secret, the algorithm specified in the header, and sign that.


QA

当用户注销时,如何使该Token失效

因为JWT无状态,不保存用户设备信息,没法单纯使用它完成以上问题,因此需要利用数据库保存一些状态完成。

  • session: 只需要把user_id对应的token清掉即可
  • JWT: 使用Redis,维护一张黑名单,用户注销时加入黑名单(签名),其中key的过期时间与JWT的过期时间保持一致,确保注销后的Token不能再被使用。

如何允许用户只能在一个设备登录,如微信

  • session: 假设使用MySQL,对用户数据库表添加token字段并加索引,每次登陆重置token字段。每次请求需要权限接口时,根据token查找user_id。
  • JWT: 假设使用MySQL,对用户数据库表添加token字段(不需要添加索引),每次登陆重置token字段。每次请求需要权限接口时,根据JWT获取user_id,根据user_id查用户表获取token判断token是否一致。另外也可以使用计数器的方法。

如何允许用户只能在最近五个设备登录

  • session: 假设使用MySQL,创建token数据库表,有id、token和user_id三个字段,user与token表为1:m关系。每次登录添加一行记录。根据token获取user_id,再根据user_id获取该用户有多少设备登录,超过5个,则删除最小id一行。
  • JWT: 假设使用MySQL,使用计数器,在用户表中添加字段count,默认值为0,每次登录count字段自增1,每次登录创建的JWT的Payload中携带数据current_count为用户的count值。每次请求权限接口时,根据JWT获取count以及current_count,根据user_id查用户表获取count,判断与current_count差值是否小于5。

如何允许用户只能在最近五个设备登录,而且使某一用户踢掉除现有设备外的其它所有设备

  • session: 在上一个问题的基础上,删掉该设备以外其它所有的token记录。
  • JWT: 在上一个问题的基础上,对count+5,并对该设备重新赋值为新的count。

小结

从以上问题得知,如果不需要控制登录设备数量以及设备信息,无状态的JWT是一个不错的选择。一旦涉及到了设备信息,就需要对JWT添加额外的状态支持,增加了认证的复杂度,此时选用session是一个不错的选择。JWT不是万能的,是否采用JWT,需要根据业务需求来确定。

Reference

A typical HTTP session: https://developer.mozilla.org/en-US/docs/Web/HTTP/Session
Session (computer science): https://en.wikipedia.org/wiki/Session_(computer_science)
What is JSON Web Token: https://jwt.io/introduction/
jwt 实践以及与 session 对比: https://juejin.im/post/5b532492e51d455d6825c0cc
聊一聊JWT与session: https://juejin.im/post/5a437441f265da43294e54c3