JWT 跨域认证和授权

69 阅读4分钟

JWT(JSON Web Token)

是一种用于身份认证和授权的标准,通过在客户端和服务器之间传递JSON格式的令牌(Token),实现跨域认证和授权。

image.png JWT(JSON Web Token)是一种开放的标准(RFC 7519),用于在网络应用间传递信息的一种简洁、自包含的方式。它通过使用数字签名(或加密)来验证数据的完整性并保证数据不被篡改,因此常用于身份认证和授权场景。

JWT由三部分组成:

头部(Header)、载荷(Payload)和签名(Signature)。

image.png

1. 头部(Header):头部通常由两部分组成,第一部分是令牌的类型,例如JWT;第二部分是所使用的签名算法,例如HMAC SHA256或RSA等。

{
  "type": "JWT",
  "alg": "HS256"
}

将上面的 JSON 对象使用 Base64URL 算法(详见后文)转成字符串。

2. 载荷(Payload):载荷包含了一些声明(Claim),它是存放实际数据的地方。有三种类型的声明:注册声明(Registered Claim)、公共声明(Public Claim)和私有声明(Private Claim)。注册声明是预定义的,包括iss(颁发者)、sub(主题)、exp(过期时间)、iat(发布时间)等。公共声明是自定义的,可以根据需要添加。私有声明是提供给用户自定义的声明,但必须避免与注册声明和公共声明冲突。

  • iss (issuer):签发人
  • exp (expiration time):过期时间
  • sub (subject):主题
  • aud (audience):受众
  • nbf (Not Before):生效时间
  • iat (Issued At):签发时间
  • jti (JWT ID):编号
  • 自定义字段

3. 签名(Signature): 签名的目的是为了验证消息的发送者以及确保消息在传递的过程中没有被篡改。签名使用头部指定的算法和秘钥对头部和载荷进行加密生成的。

首先,需要指定一个密钥(secret)。这个密钥只有服务器才知道,不能泄露给用户。然后,使用 Header 里面指定的签名算法(默认是 HMAC SHA256),按照下面的公式产生签名。

HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret)

JWT的工作流程如下:

  1. 用户通过使用用户名和密码(或其他认证方式)向服务器请求身份验证。
  2. 服务器验证用户提供的身份信息,并生成一个包含用户标识和其他相关信息的JWT。
  3. 服务器将该JWT返回给客户端,客户端可以将其保存在本地,通常是在浏览器的本地存储(localStorage或cookie)中。
  4. 客户端在每次向服务器发送请求时,都需要将JWT放在请求的头部(通常是Authorization头部)中传递给服务器。
  5. 服务器收到请求后,会验证JWT的签名和有效期,并根据其中的用户标识来完成身份认证和授权。

JWT的优点包括:

  • 自包含:JWT中携带的信息是自包含的,不需要查询数据库或其他存储来验证其有效性,减轻服务器负担。
  • 可扩展:JWT可以存储任意类型的声明信息,便于在分布式系统中使用。
  • 前后端分离:由于JWT是基于令牌的身份验证机制,可以实现前后端分离的架构。

JWT 需要注意以下几点:

(1)JWT 默认是不加密,但也是可以加密的。生成原始 Token 以后,可以用密钥再加密一次。

(2)JWT 不加密的情况下,不能将秘密数据写入 JWT。

(3)JWT 不仅可以用于认证,也可以用于交换信息。有效使用 JWT,可以降低服务器查询数据库的次数。

(4)JWT 的最大缺点是,由于服务器不保存 session 状态,因此无法在使用过程中废止某个 token,或者更改 token 的权限。也就是说,一旦 JWT 签发了,在到期之前就会始终有效,除非服务器部署额外的逻辑。

(5)JWT 本身包含了认证信息,一旦泄露,任何人都可以获得该令牌的所有权限。为了减少盗用,JWT 的有效期应该设置得比较短。对于一些比较重要的权限,使用时应该再次对用户进行认证。

(6)为了减少盗用,JWT 不应该使用 HTTP 协议明码传输,要使用 HTTPS 协议传输。

(7) 如果JWT被拦截,黑客可以获得其中的信息,因此不要在JWT中存放敏感数据。

在实际应用中,可以选择合适的JWT库或框架来实现JWT的生成、验证和解析,以方便地使用JWT进行身份认证和授权。

Base64URL

前面提到,Header 和 Payload 串型化的算法是 Base64URL。这个算法跟 Base64 算法基本类似,但有一些小的不同。

JWT 作为一个令牌(token),有些场合可能会放到 URL(比如 api.example.com/?token=xxx)。Base64 有三个字符+/=,在 URL 里面有特殊含义,所以要被替换掉:=被省略、+替换成-/替换成_ 。这就是 Base64URL 算法。

参考连接: www.ruanyifeng.com/blog/2018/0…