token、session的对比及 JWT 的使用 | 青训营笔记

242 阅读3分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 10 天

最近在做项目的时候,遇到了token,写下此篇文章作为记录。

首先当我们有这样一个需求: 当客户端请求服务端某些服务的时候,我们需要其满足一定的条件,比如:必须登陆后才能请求特定的服务。这个时候,我们对来自客户端的请求就需要一次用户验证,验证其是否已经登陆了。

Session认证方式

原理:

因为http协议本身就是一种无状态的协议,每次有请求过来的时,我们并不知道是哪个具体的用户的发出的请求,所以为了达到这样的目的,我们要在服务端存储一份用户信息,并且将这份用户信息传回给浏览器(客户端),告诉其保存为cookie,以便客户端下次请求的时候携带这份用户信息,这样服务端就能识别请求来自哪个用户。 如图:

流程图 (2).jpg

弊端:

  1. 当用户第一次认证的时候,都会在服务端保存一份session,以便以后的验证,很明显随着用户的增加,服务端的开销会越来越大。
  2. 当在分布式的场景下,若是session保存在服务器的内存中,那就必须要求客户端的下次请求必须是发往之前的服务器的时候,这样才能找到对应的session,很明显这样使得拓展性大大降低,并且限制了负载均衡的能力。
  3. session是基于cookie来实现的,然而cookie本身就是不安全的,当cookie被获取,服务端收到csrf攻击。
  4. 在前后端分离的项目中,应用解耦,一个请求通常会被转发多次,每次都携带session到服务器,服务端每次还要查询信息,负担会持续加重。

JWT认证方式

JWT:json wev token

原理:

通过JSON形式作为Web应用中的令牌,用于在各方之间安全地将信息作为JSON对象传输。在数据传输过程中还可以完成数据加密、签名等相关处理。简而言之,JWT就是一个加密的字符串,作为验证信息在计算机之间传递,只有可以访问加密密钥的计算机才能对其进行解密,从而验证携带这个令牌(Token)的请求是否合法。 如图:

流程图 (1).jpg

JWT的组成:

令牌的组成:

1. header 头部:有令牌的类型和所使用的签名算法,如HMAC、SHA256、RSA;使用Base64编码组成;(Base64是一种编码,不是一种加密过程,可以被翻译成原来的样子)

2. payload 载荷:有效负载,包含声明,声明是有关实体(通常是用户)和其他数据的声明,不放用户敏感的信息,如密码。同样使用Base64编码

3. signature 签名:前面两部分都使用Base64进行编码,前端可以解开知道里面的信息。Signature需要使用编码后的header和payload加上我们提供的一个密钥,使用header中指定的签名算法进行签名。签名的作用是保证JWT没有被篡改过。当要对新的头部和负载进行签名,如果不知道服务器的密钥的话,那么得出来的签名也是不一样的

token格式:header.payload.signature 类似于xxxx.yyyy.zzzz

如图:

image.png

JWT的优点

  1. 简洁(Compact):可以通过URL,POST参数或者在HTTP header发送,数据量小,传输速度也很快;

  2. 自包含(Self-contained):负载中包含了所有用户所需要的信息,避免了多次查询数据库;

  3. Token是以JSON加密的形式保存在客户端,所以JWT是跨语言的,原则上任何web形式都支持。

  4. 不需要在服务端保存会话信息,特别适用于分布式微服务。

参考学习文献:

  1. go-jwt
  2. jwt理解
  3. jwt官网