认证授权(二)-JWT

一、定义

JSON Web Token (JWT)是一个开放标准(RFC 7519),它定义了一种紧凑的、自包含的方式,用于作为JSON对象在各方之间安全地传输信息。该信息可以被验证和信任,因为它是数字签名的。

优点:

1.payload 可存储业务逻辑信息(非敏感性)

2.JWT可以使用一种加密算法比如HMAC 算法,也可以使用公钥/私钥的非对称算法

3.因为JWT签名后的信息够短,可以放在url里、request body里、http header里,传输够快。

4.不需要存储在服务端,易于扩展

二、使用场景

下列场景中使用JSON Web Token是很有用的:

  • Authorization (授权) : 这是使用JWT的最常见场景。一旦用户登录,后续每个请求都将包含JWT,允许用户访问该令牌允许的路由、服务和资源。单点登录是现在广泛使用的JWT的一个特性,因为它的开销很小,并且可以轻松地跨域使用。
  • Information Exchange (信息交换) : 对于安全的在各方之间传输信息而言,JSON Web Tokens无疑是一种很好的方式。因为JWTs可以被签名,例如,用公钥/私钥对,你可以确定发送人就是它们所说的那个人。另外,由于签名是使用头和有效负载计算的,您还可以验证内容没有被篡改。

三、JWT流程

  1. 用户使用用户密码来请求服务器
  2. 服务器进行验证用户信息
  3. 服务器通过验证发送用户一个token
  4. 客户端存储token,并在每次请求时在HTTP头附送上这个token值
  5. 服务端验证token值,从token解析到用户信息,处理后并返回数据

 四、JWT结构

JSON Web Token由三部分组成,它们之间用圆点(.)连接。这三部分分别是:

  • Header
  • Payload
  • Signature

因此,一个典型的JWT看起来是这个样子的:

xxxxx.yyyyy.zzzzz

扫描二维码关注公众号,回复: 3673114 查看本文章

接下来,具体看一下每一部分:

1.Header

JWT 的 header 中承载了两部分信息

{
  "alg": "RS256",
  "typ": "JWT"
}
  • alg: 声明加密的算法
  • typ: 声明类型

对这个头部信息进行 base64,即可得到 header 部分

const headerBuff = Buffer.from(
  JSON.stringify({
    alg: "RS256",
    typ: "JWT"
  })
);

const header = headerBuff.toString("base64");

console.log(header);
// eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9

2.Payload

payload 是主体部分,意为载体,承载着有效的 JWT 数据包,它包含三个部分

  • 标准声明
  • 公共声明
  • 私有声明

标准声明的字段

interface Stantar {
  iss?: string; // JWT的签发者
  sub?: string; // JWT所面向的用户
  aud?: string; // 接收JWT的一方
  exp?: number; // JWT的过期时间
  nbf?: number; // 在xxx日期之间,该JWT都是可用的
  iat?: number; // 该JWT签发的时间
  jti?: number; //JWT的唯一身份标识
}

标准中建议使用这些字段,但不强制。

公共声明的字段

interface Public {
  [key: string]: any;
}

公共声明字段可以添加任意信息,但是因为可以被解密出来,所以不要存放敏感信息。

私有声明的字段

interface Private {
  [key: string]: any;
}

私有声明是 JWT 提供者添加的字段,一样可以被解密,所以也不能存放敏感信息。

上面的 JWT 的 payload 结构是这样的

{
  "ip": "127.0.0.1",
  "uuid": "ff1212f5-d8d1-4496-bf41-d2dda73de19a",
  "iat": 1527523017
}

同样是通过 base64 加密生成第二部分的 payload

const payloadBuffer = Buffer.from(
  JSON.stringify({
    ip: "127.0.0.1",
    uuid: "ff1212f5-d8d1-4496-bf41-d2dda73de19a",
    iat: 1527523017
  })
);

const payload = payloadBuffer.toString("base64");

console.log(payload);
// eyJpcCI6IjEyNy4wLjAuMSIsInV1aWQiOiJmZjEyMTJmNS1kOGQxLTQ0OTYtYmY0MS1kMmRkYTczZGUxOWEiLCJpYXQiOjE1Mjc1MjMwMTd9

3.Signature

signature 是签证信息,该签证信息是通过headerpayload,加上secret,通过算法加密生成。

公式 signature = 加密算法(header + "." + payload, 密钥);

上面的 header 中,我们已经定义了加密算法使用 RS256,也已经实现了生成headerpayload,下面我们来生成 signature

const crypto = require("crypto");
const sign = crypto.createSign("SHA256");
const secret = `私钥,太长我就不贴出来了`;

sign.write(header + "." + payload);
sign.end();

const signature = sign
  .sign(secret, "base64")
  // 在JWT库中,已经把这些字符过滤掉了
  .replace(/=/g, "")
  .replace(/\+/g, "-")
  .replace(/\//g, "_");

console.log(signature);

到此,已经实现了如何生成一个 JWT 的 token.

五、JWT与Session的区别

  • Session 通过 cookie 传输,存储在服务器,服务器通过 cookie 中的 sessionID 获取当前会话用户,对于单台服务器没问题,但多服务器就涉及到共享 Session ,而且认证用户多时 Session 会占用大量服务器内存
  • JWT 存储在客户端,服务器不需要存储 JWT ,JWT 里有用户 ID,服务器拿到 JWT 后验证可以获得用户信息,也就实现了 Session 功能,但是是无状态的,只要签名秘钥足够安全就能保证 JWT 可靠性

六、JWT与OAuth的区别

  • OAuth2是一种授权框架 ,JWT是一种认证协议
  • 无论使用哪种方式切记用HTTPS来保证数据的安全性
  • OAuth2用在使用第三方账号登录的情况(比如使用weibo, qq, github登录某个app),而JWT是用在前后端分离, 需要简单的对后台API进行保护时使用。

猜你喜欢

转载自blog.csdn.net/haoxin963/article/details/82860284