JWT Token: 轻量级的, 基于Token的身份验证(译)

Posted by     "" on Monday, June 3, 2019

TOC

原文: https://dzone.com/articles/jwt-token-lightweight-token-based-authentication

确保网站的安全是每个开发者的目标. 如今, 有各种方法来解决网站的安全. 对于HTTP协议, 会有一些难点, 因为它是无状态的.

什么是无状态?

当一个客户端给服务端发送一个请求, 服务端处理完后, 将处理结果发回给客户端. 然后, 这个流程就结束了, 状态也关闭了. 对于下一个请求, 即使它是同一个客户端发出去的, 也会被看成是一个新的请求或是一个新的状态. 总之, 对服务端来说, 每一个请求都是新的.

在这种情况下,如果客户端需要访问一个受保护的资源,那么服务端必须对客户端进行身份验证并验证其真实性,以确保它具有访问资源的权限. 这是通过凭证完成的身份验证.

由于每个请求都是无状态的, 是否需要每次都发送用户名/密码. 当然, 这是可以的, 但不够灵活. 有很多种机制可以解决这个问题, 其上一个就是基于token的身份验证(token-based authentication).

什么是基于Token的身份验证(Token-Based Authentication)?

在这种机制下, 当服务端第一次接收到用户名和密码时, 会将它与数据中的数据(通过注册收集)进行比对, 确保它有权限访问受保护的资源. 与此同时, 服务端会生成一个token, 保存在数据库中, 并附加在给客户端的响应中. 在接下来的请求中(同一用户), 把token放在请求包中, 不用再发送用户名和密码. 服务端会将这个token与数据库中的token比对, 进验证和鉴权, 以确保这个用户是否可以访问相应的资源.

业界有很多种基于token的身份验证机制, 有一个是JSON web token(JWT). OAuth是另外一个比较有名的机制. JWT采用了一种不同的技术使其更安全,这种技术就是签名. 这可以防止恶意用户检索和篡改token.

什么是JWT Token?

JSON web令牌(JWT)是一种开放标准(RFC 7519),它是一种紧凑且自包含的(self-contained)方式,用于作为JSON对象在系统之间安全地传输信息. 这个信息是可以被验证和可靠的, 因为它是基于数字签名的. 可以使用密钥(基于HMAC算法)对JWT进行数字签名, 也可以使用基于RSA(或)ECDSA的公钥/私钥对.

为会么使用JWT Token?

安全

JWT是基于数字签名的, 只有服务端知道加密时使用的密钥, 所以这是非常安全的. 如果在传输过程中, JWT发生了变化, 那么系统可以检测出来, 并报错说”无效的签名”.

简洁

JWT是一个字符串, 由一个简单的JSON对象经编码而成, 这个JSON对象可以保存系统之间传输的所有信息. 由此可见, JWT是很小的, 可以通过URL, POST参数, 或HTTP Headers来传输.

因为它很简洁, 且仅仅是一个对象, 所以传输速度会非常的低. 另外, 它保存着很多有用的信息, 不需要再去数据库中获取, 因此可以节省不少的时间.

自包含(Self-Contained)

因为JSON token保存着足够的关于用户的数据, 它不需要多次地访问数据库.

简单

JSON没有XML那么冗余, 更加的简洁和更小尺寸. 还有一些很不错的debugging工具可以查看JWT的信息(注意: 不要把私密的数据放入token中).

应该在什么时候作用JWT Token?

认证和授权

每当用户成功登录, 服务器都会生成一个JWT token, 并附带在响应中. 在接下来的每个请求中, 这个token都会发送给服务端. 这个JWT token保存着用于鉴权的用户信息.

信息交换

JWT可以使用公钥/私钥对, 所以它也可以被用于在两个系统之间交换数据.

我们已经知道足够的JWTs的信息了, 现在, 我们来了解JWT的结构.

JWT的结构

基本上, JWT Token是一个纯的JSON对象, 所以它有自己的结构.

JWT Structure

header保存着数字签名算法和token的类型.

这是由服务端生成的token元数据. 对象生成这之后, 将使用Base64URL对其进行编码, 以形成JWT token的第一部分.

JWT - Header

Payload

payload保存的是一个数据集, 当客户端把token发送给服务端时, 服务端可以使用里面的数据. 这个数据集通常是一些用户的信息. 另外, 不应该把任何关于用户的敏感信息放入其中, 比如: 密码, 邮箱等.

payload里保存着claims, claims的类型有三种, 分别是: registered, 公有的和私有的.

JWT  - Payload

Registered claims: 是一组预定义, 有用的, 可互操作的claims. 建议使用它们, 但不是强制性的. 其中一些是:

  • iss(issuer): 签发人
  • exp(expiration time): 过期时间
  • nbf(not before):生效时间
  • iat(issued at):签发时间
  • 等等

注意: 为了保存简洁, 这些claim的名字都只有3个字母.

公有claims: 可以由使用JWTs的用户随意定义. 私有claims: 这些是为了在系统之间共享信息而创建的自定义claims.

payload对象创建完成后,将使用Base64Url对其进行编码,以形成JWT令牌的第二部分.

签名

JWT - Signature

签名的作用是对Header和Payload进行编码, 编码所需的算法在Header中指定. 此外, 还需要一个密钥, 这个密钥只有服务端知道. 如果JWT Token中的内容出现了改动, 将会被标记为”非法的”.

下面例子是一个真实的token:

JWT - Signature

JWT Token是如何工作的?

  1. 用户通过用户名和密码进行登录.
  2. 服务端根据数据库中的信息, 对用户的用户名和密码进行验证.
  3. 根据用户的信息和权限, 调用JWT的库生成一个JWT. 注意不要把敏感的信息放到token中, 因为token是可以被解密的. 在发送token前, 将token保存在数据库中.
  4. 在接下来的请求中, 用户都把token放在header中, 发回给服务端.
  5. 服务端对token进行解码并对其进行验证, 然后授予用户访问服务器中受限资源的权限.
  6. 一旦用户进行了注销, 应该清除这个JWT Token.

总结

如今, 很多网站都用基于JWT Token的身份验证方式替换了旧的验证方式. 这是一个简洁又轻量的机制. 与其他的token机制相比, 它更加的适合, 并且实现和管理起来也简单.

感谢大家阅读这篇文章, 我希望可以给你一个关于JWT Token的想法. 这是一种被广泛采用的方法, 有很多库可以帮助使用任何技术实现JWT.

「真诚赞赏,手留余香」

AbeWang's Blog

真诚赞赏,手留余香

使用微信扫描二维码完成支付


comments powered by Disqus