JWT(JSON WEB Token)

标签: JWT

今天尝试把用户权限注册部分托管到AWS服务上,而发现相关的服务是AWS cognito。
同样是基于oauth2的授权模式,但里面返回不是我们原来使用的那种token,而是另一种JWT(JSON WEB Token)。这里只介绍JWT,具体实现后面在用一篇文章进行介绍。

协议官网:
https://jwt.io/introduction/

1 什么是JSON Web Token

JSON Web Token(JWT)是一个开放标准(RFC 7519),它定义了一种紧凑且独立的方式,可以在各方之间作为JSON对象安全地传输信息。此信息可以通过数字签名进行验证和信任。JWT可以使用秘密(使用HMAC算法)或使用RSA或ECDSA的公钥/私钥对进行签名,确保了信息的安全。

2 JSON Web Token 用途

以下是JSON Web令牌有用的一些场景:

  1. 授权:这是使用JWT的最常见方案。一旦用户登录,每个后续请求将包括JWT,允许用户访问该令牌允许的路由,服务和资源。SingleSign On(单点登录)是一种现在广泛使用JWT的功能,因为它的开销很小,并且能够在不同的域中轻松使用。
  2. 信息交换:JSON Web令牌是在各方之间安全传输信息的好方法。因为JWT可以签名 - 例如,使用公钥/私钥对您可以确定发件人是他们所说的人。此外,由于使用标头和有效负载计算签名,您还可以验证内容是否未被篡改。
  3. 一次性登录及restful API

将JSON Web Token用于资源服务器(RS256加密的情况下):
这里写图片描述

3 JSON Web Token结构

JSON Web Token由三个部分组成(由点(.)分隔,它们是:
- 头(header)
- 有效载荷(payload)
- 签名(Signature)
因此,JWT通常如下所示:

xxxxx.yyyyy.zzzzz
Header.payload.signature

它们以 Base64url 字符串的格式编码(也就可以解码),并且用点“.”characters. 如果您的 JWT 不符合此结构,请将其视为无效,且不得接受它。

3.1 JWT header

标头通常由两部分组成:令牌的类型,即JWT,以及正在使用的散列算法,例如HMAC SHA256或RSA。
例如:

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

这两个KEY其实并没有被强制要求。比如在AWS 提供的JWT header中,alg表示加密算法类型,typ被替换成了kid (key id),用于标识解密该JWT的公匙id。

header这个JSON被编码为Base64Url,形成JWT的第一部分。

3.2 JWT Payload

令牌的第二部分是有效负载。声明是关于实体(通常是用户)和其他数据Cliam(声明、权利)。声明有三种类型:registered(保留), public(公开), and private claims(私人)。这三种声明类型及约定了payload该类型中某些成员组成。

3.2.1 registered claims(建议但不强制)

iss: jwt签发者
sub: jwt所面向的用户
aud: 接收jwt的一方
exp: jwt的过期时间,这个过期时间必须要大于签发时间
nbf: 定义在什么时间之前,该jwt都是不可用的.
iat: jwt的签发时间
jti: jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击。

3.2.2 public claims

公共的声明可以添加任何的信息,一般添加用户的相关信息或其他业务需要的必要信息.但不建议添加敏感信息,因为该部分在客户端可解密.

3.2.3 private claims

私有声明是提供者和消费者所共同定义的声明

3.2.4 payload sample

示例有效负载可以是:

{
  "sub": "1234567890",
  "name": "John Doe",
  "admin": true
}

然后,有效负载经过Base64Url编码,形成JSON Web令牌的第二部分。

重要:请注意,对于签名令牌,此信息虽然可以防止被篡改(因为签名会对header和payload进行哈希,header和payload被篡改后,签名即会不一致),但任何人都可以读取。除非加密,否则不要将秘密信息放在JWT的有效负载或头元素中。

3.3 Signature

要创建签名部分,您必须采用编码标头,编码的有效负载,secret,标头中指定的算法,并对其进行签名。

例如,如果要使用HMACSHA256算法(HS256-对称加密),将按以下方式创建签名:

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

签名用于验证消息在此过程中未被更改。并且,在使用私钥签名的令牌的情况下(RS256-非对称加密),它还可以验证JWT的发件人是否是它所声称的人。

  • RS256(带SHA-256的RSA签名)是一种非对称算法,它使用公钥/私钥对:身份提供者具有用于生成签名的私有(秘密)密钥,JWT的消费者获得公钥验证签名。由于与私钥相对的公钥不需要保持安全,因此大多数身份提供商使消费者可以轻松获得和使用(通常通过元数据URL)。即对date进行哈希,然后使用私匙对哈希进行签名。另一方可以对同样内容进行哈希,然后与解密后的内容进行对比。这样就可以确定发件人身份。
  • HS256(HMAC与SHA-256)是对称算法,只有一个(秘密)密钥在双方之间共享。由于使用相同的密钥来生成签名并对其进行验证,因此必须注意确保密钥不受损害。即HS256仅仅是对(data secret)进行哈希,secret(salt)为双方共享。该算法只能保证哈希结果不一致,但不能确定身份。

3.4 一个JWT sample

下面展示了一个JWT(HS256),它具有先前的头和​​有效负载编码,并使用secret签名。

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJoZWxsb3dvcmxkIiwibmFtZSI6ImFuZHkgTGkiLCJpYXQiOjE1MTYyMzkwMjJ9.QjmCihtb7jFgt1wtjsYow9OEquTZ6MPV4RK6RWkHUUw

完整JWT:

header:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
payload:eyJzdWIiOiJoZWxsb3dvcmxkIiwibmFtZSI6ImFuZHkgTGkiLCJpYXQiOjE1MTYyMzkwMjJ9
Signature:QjmCihtb7jFgt1wtjsYow9OEquTZ6MPV4RK6RWkHUUw

3.5 如何使用令牌

每当用户想要访问受保护的路由或资源时,用户可以使用header发送JWT,通常在Authorization 头中。header的内容应如下所示:

Authorization: Bearer <token>
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJoZWxsb3dvcmxkIiwibmFtZSI6ImFuZHkgTGkiLCJpYXQiOjE1MTYyMzkwMjJ9.QjmCihtb7jFgt1wtjsYow9OEquTZ6MPV4RK6RWkHUUw

如果存在,则允许用户访问受保护资源。如果JWT包含必要的数据,则可以减少查询数据库以进行某些操作的需要,尽管可能并非总是如此。

3.6 关于浏览器端存储JWT Token

浏览器有两个地方可以用于存储JWT
- HTML5 Web Storage (localStorage或sessionStorage)
- Cookies
应该被保存起来,放到 local / session stograge 或者 cookies.

存储在这两个位置安全性风险对比

  1. Web存储(localStorage/sessionStorage)可以通过同一域上JavaScript访问。这意味着任何在你的网站上运行的JavaScript都可以访问Web存储,因为这样容易受到跨站点脚本(XSS)攻击。应用场景,在标Authorization头中发送令牌,则跨域资源攻击(CORS)将不会成为问题,因为它不会使用到cookie。
  2. Cookies,当使用带有HttpOnly的cookie标志时,通过JavaScript是无法访问的,并且对XSS是免疫的。,cookies容易受到不同类型的攻击:跨站点请求伪造(CSRF)。

建议将JWT存储在cookie中,并设置HttpOnly,利用web应用程序框架的CSRF保护从API通过检查HTTP Referer和原始header进行阻止CSRF攻击,检测攻请求来源。这样可以防止 XSS 攻击和 CSRF 攻击都可以防御

3.7 注意

请注意,使用签名令牌,令牌中包含的所有信息都会向用户或其他方公开,即使他们无法更改。这意味着您不应该在令牌中放置秘密信息。

4 JSON Web Token优缺点

4.1优点

1 比较用于单点的登录(SSO-在一个多系统共存的环境下,用户在一处登录后,就不用在其他系统中登录,也就是用户的一次登录能得到其他所有系统的信任),因为其他系统通过URL的方式获取到公匙,后续既可以确认用户身份及JWT真伪, 还比较适合和一次性登录及restful API。
2 降低数据库压力,JWT可以在自身存储一些其他业务逻辑所必要的非敏感信息。
3 安全性较高,可以防止token被篡改
4 跨语言,支持多种语言的实现
关于CSRF: https://blog.csdn.net/stpeace/article/details/53512283

4.2 缺点

  1. JWT生成后,本身不可控,如果不做其他处理,只有等本身Token过期时间到了才能失效。比较典型的场景就是用户更改密码后,原来JWT仍然有效(因为公匙仍然认可JWT来自认证方且没有被篡改)
  2. 消息体可以被base64解密为明文

5 参考链接

JWT官网:https://jwt.io/introduction/
JWT介绍:https://mp.weixin.qq.com/s?__biz=MzI0NzEyODIyOA==&mid=2247483918&idx=1&sn=12683bae55f2ab1a8281ab398472362f&chksm=e9b58bc5dec202d385d1c1d861f7e0ff495296ed9387b32a8d01ae195eae03688e5aeebe6396&mpshare=1&scene=23&srcid=0505snLrWQ4JjwVW94oSMJaK#rd
关于浏览器JWT存储:https://www.jianshu.com/p/e91fa0eaddd1
session与JWT比较:https://www.jianshu.com/p/78e15a1ac7f2

版权声明:本文为m0_37263637原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/m0_37263637/article/details/81165271