五分钟 ! JTW 快速入门系列

518 阅读7分钟

世界上最快的捷径,就是脚踏实地,本文已收录【架构技术专栏】关注这个喜欢分享的地方。

JSON Web Token(JWT)是什么?

WT作为一个开放的标准(RFC 7519), 定义了一种简洁自包含的方法用于通信双方之间以Json对象的形式安全的传递信息。 因为特定的数字签名,所以这些通信的信息能够被校验和信任。 JWT可以使用HMAC算法或者RSA的公钥私钥对进行签名。

让我们进一步的解释下关于JWT的定义:

  • 简约(Compact): JWT通信中使用的数据量比较小,JWT可以通过URL、POST参数,或者直接在HTTP header进行传递。 并且,因为比较小的数据量,这也意味着传输速度会更加快速。

  • 自包含(Self-contained): 负载(payload)中(可以)包含所需的所有用户部分的信息,可以避免对服务端数据库的多次查询。

什么时候应该使用JSON Web Tokens?

以下是JSON Web Tokens适用的一些场景:

  • 认证鉴权(Authentication): 这是JWT最常用的场景,一旦用户成功登入,在随后的每次请求中都将会包含JWT信息。 通过JWT的验证机制后,将允许该用户访问路由(routes)、服务(services)以及该Token所允许的资源。由于JWT的开销非常小, 使得其可以轻松的在不同的域名中传递,所以目前在单点登录(Single Sign On)中有比较广泛的应用。

  • 数据交换(Information Exchange):JSON Web Tokens是一种很好的安全传输方式,因为JWTs是可签名的- 例如基于使用公钥/私钥对,你可以确保请求的发送者是可信的。另外,因为参与签名是是头部信息(header)和负载信息(payload), 您可以可以验证内容是否被篡改。

JSON Web Token是一种什么样的结构?

JSON Web Tokens 包含使用使用(.)分隔开的三部分, 这三部分分别是:

  • 头部 Header
  • 负载 Payload
  • 签名 Signature

因此, JWT通常看起来如下所示.

xxxxx.yyyyy.zzzzz

接下来让我们来分解不同的部分:

头部(Header)

header 通常包含两部分的信息: token的类型, 如JWT, 以及token使用的加密算法, 如 HMAC SHA256或者RSA.

例:

{
"alg": "HS256",

"typ": "JWT"
}

接下来, 这部分JSON内容经过Base64Url 编码来组成JWT的第一部分结构信息.

负载(Payload)

JWT token的第二部分是payload, Payload包含claims. Claims是一些实体(通常指用户)的状态信息和其他元数据。 有三种类型的claims: registered, public, 和 private

  • Registered claims: 这些claims是预先定义的,在JWT中并不强制使用这些claims,但是推荐使用这些有效而又约定俗成的claims,比如: iss (issuer 签发者), exp(expiration time 过期时间), sub (subject 面向的用户), aud (audience 接收方 )和 其他更多的claims.

    请注意,声明名称约定只有三个字符的长度,因为JWT旨在短小紧凑。

  • Public claims: 这些claims可以由开发人员自由定义,但为了避免出现冲突,应该在 IANA JSON Web Token Registry中定义他们, 或者将其定义为包含防止冲突命名空间的URI。

  • Private claims: 这里放置的是自定义claims,若既没有在registered 也没有在 public中定义的话,双方可以使用此claims 来进行信息之间的交换。

一个负载(payload)的示例:

{
"sub": "1234567890",

"name": "John Doe",

"admin": true
}

负载(payload)部分经过 Base64Url 编码来组成JWT的第二部分结构信息.

Signature

要创建签名部分,需要使用经过编码后的头部(header)和负载(payload)以及一个密钥,使用在头部(header)中指定的算法进行签名。

举个例子,如果说你希望使用 HMAC SHA256 algorithm进行签名,那么签名将会如下所示方式进行创建:

HMACSHA256(

base64UrlEncode(header) + "." +

base64UrlEncode(payload),

secret)

该签名是用户验证JWT的请求发送者以及确保数据信息在传输过程中的消息是未经篡改的。

整合JWT

JWT的最终输出,是由以.分隔的三段Base64编码后的字符串,可以在HTML和HTTP环境中轻松的传递,而与基于XML的标准如SAML相比 JWT则更加紧凑。

用下面这个完整的JWT举例,它即是以先前的头部(Header), 负载(Payload)以及秘钥签名而成。

如果你想使用JWT,并期望将这些概念付诸实践,你可以使用jwt Debugger来解码,验证和创建JWT。

JSON Web Tokens是如何工作的?

在身份鉴权中,当用户使用它们的凭据(通常是账户密码)成功登录时,JSON Web Token将会返回给用户侧,并且该JWT必须保存在本地 (通常是保存在local storage, 不过也可以使用cookies来进行存储)。JWT使用此方式,而不是在传统的方法中服务端创建一个session,然后 服务端返回一个与之对应的cookie。

无论何时,当用户想要访问一个受保护的路由或者资源,用户都应该在请求中发送JWT,通常是在请求头(Request Header)的 Authorizationheader信息中使用Bearer的模式,如下所示:

Authorization: Bearer <token>

真实案例如下:

Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsImp0aSI6IjRmMWcyM2ExMmFhIn0.eyJpc3MiOiJodHRwOlwvXC9leGFtcGxlLmNvbSIsImF1ZCI6Imh0dHA6XC9cL2V4YW1wbGUub3JnIiwianRpIjoiNGYxZzIzYTEyYWEiLCJpYXQiOjE1MjA5MjkxMjcsIm5iZiI6MTUyMDkyOTE4NywiZXhwIjoxNTIwOTMyNzI3LCJpZCI6MTAwMDAsInVpZCI6MTAwMDAsInRlc3RQYXJhbSI6Njc3fQ.AVO6eUwUIcdnCJ1QXAGPobkNruijgFB2EupHbVfk-OA

因为用户的状态在服务端的内存中是不会被存储的,所以这是一种无状态的身份验证机制。受服务端保护的路由将校验Authorization header 中的JWT信息,如果校验合法,用户将会被允许访问受保护的资源。由于JWT是自包含的,所有必要的基础信息都在JWT中,这样就避免了多次 对数据库的查询操作。

JWT的这些特性,使得开发者可以完全依赖无状态的数据API,甚至向下游服务提交请求。因为它的实现并不基于cookie,所以是哪个域名提供 的API服务就变得无关紧要,因此跨域资源共享(CORS)不会成为应用中的问题。

下图就给大家展示了这个流程:

为什么我们需要使用JSON Web Tokens?

让我们谈谈 Simple Web Tokens (SWT) 与 **安全声明标记语言 Security Assertion Markup Language Tokens (SAML)**相比的优势吧。

相比XML格式,JSON更加的简洁,经过编码之后更小,这使得JWT比SAML更加简洁轻巧,更加适合在HTML和HTTP的场景中应用。

在安全性方面,SWT只能够通过使用HMAC算法的共享密钥队形对称签名,而JWT和SAML token则可以使用X.509认证的公钥/私钥对进行签名。 与JSON的简单性相比,通过XML数字签名签署XML会更加容易引入复杂的安全漏洞

因为JSON可以直接映射到对象,在大多数编程语言中都提供了JSON解释器,而XML则没有怎么自然的文档到对象的映射,这就使得使用JWT 比SAML更加方便

关于使用,JWT在互联网上已经有了大规模的使用,这也突出在针对多平台上的易用性上,尤其是JWT在移动客户端上有天然的的简易性。

总结

JWT 的特点:

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

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

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

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

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

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

资料:jwtio.online/introductio…