NodeJs基于Token的身份认证

Caleb2020年6月8日
大约 3 分钟...约 968 字

传统的 Session 验证

起初的验证方式是存在于服务器的,用户登录进来以后,服务器判断成功,将数据存进 session 里面,向用户返回一个 sessionID。这样的弊端是,假如用户基数特别大,每登录一个用户,就要存储一条,对服务器的内存压力比较大。

基于 Token 的验证方法

基于 Token 的验证方法是无状态的,因此我们就不用把信息存在服务器中了。

Token 可以通过请求头传输,所以他可以在任何一种 http 请求中被发送到服务器中。

Token 的验证流程

客户端发送用户、密码到服务器。
服务器接收到信息之后和数据库进行比对,验证成功后,生成一段有时效的Token字符串,向客户端返回登陆成功信息以及Token字符串。
客服端接收到信息,将Token存储在Local Storage或者Cookies中。
客服端再向服务器发送请求时,将Token放在请求头中。
服务器先解析请求头中的Token,如果解析成功,那么就进入业务逻辑中,如果不成功返回错误信息。

nodeJS(express) + jwt(jsonwebtoken)

首先安装 jsonwebtoken

npm install jsonwebtoken -S

然后在服务器中创建一个 js 文件,可以自行命名,我在这里命名为jwt.js

// 引入模块依赖
const fs = require("fs");
const path = require("path");
const jwt = require("jsonwebtoken");
// 创建 token 类
class Jwt {
  constructor(data, key, minute) {
    this.data = data;
    this.keyword = key;
    this.minute = minute || 30;
  }
  //生成token
  generateToken() {
    let data = this.data;
    let minute = this.minute;
    let keyword = this.keyword;
    let created = Math.floor(Date.now() / 1000);
    let exp = created + 60 * minute;
    let cert = fs.readFileSync(path.join(__dirname, "../pem/rsa_private_key.pem")); //私钥 可以自己生成
    let token = jwt.sign(
      {
        data: {
          id: data,
          key: keyword,
        },
        exp,
      },
      cert,
      {
        algorithm: "RS256",
      }
    );
    return token;
  }

  // 校验token
  verifyToken() {
    let token = this.data;
    let cert = fs.readFileSync(path.join(__dirname, "../pem/rsa_public_key.pem")); //公钥 可以自己生成
    let res;
    try {
      let result =
        jwt.verify(token, cert, {
          algorithms: ["RS256"],
        }) || {};
      let { exp = 0 } = result,
        current = Math.floor(Date.now() / 1000);
      if (current <= exp) {
        res = result.data || {};
      }
      return res;
    } catch (e) {
      res = "err";
    }
  }
}

module.exports = Jwt;

解析

generateToken

jwt.sign(payload, secretOrPrivateKey, [options, callback]);

payload ==> 代指要存进的内容
secretOrPrivateKey ==> 秘钥,我这里使用的是生成的私钥加密,也可以使用不规则字符。
[options, callback] ==> 参数,包括支持的算法等等

verifyToken

jwt.verify(token, secretOrPublicKey, [options, callback]);

token ==> sign生成的Token
secretOrPublicKey ==> 使用生成的公钥解密。
[options, callback] ==> 使用相同的解密方式

具体参数

可以查看jsonwebtokenopen in new window在 npm 上的详细解释

支持的算法

参数值数字签名或 MAC 算法
HS256使用 SHA-256 哈希算法的 HMAC
HS384使用 SHA-384 哈希算法的 HMAC
HS512使用 SHA-512 哈希算法的 HMAC
RS256使用 SHA-256 哈希算法的 RSASSA-PKCS1-v1_5
RS384使用 SHA-384 哈希算法的 RSASSA-PKCS1-v1_5
RS512使用 SHA-512 哈希算法的 RSASSA-PKCS1-v1_5
PS256使用 SHA-256 哈希算法的 RSASSA-PSS(only node ^ 6.12.0 OR> = 8.0.0)
PS384使用 SHA-384 哈希算法的 RSASSA-PSS(only node ^ 6.12.0 OR> = 8.0.0)
PS512使用 SHA-512 哈希算法的 RSASSA-PSS(only node ^ 6.12.0 OR> = 8.0.0)
ES256使用 P-256 曲线和 SHA-256 哈希算法的 ECDSA
ES384使用 P-384 曲线和 SHA-384 哈希算法的 ECDSA
ES512使用 P-521 曲线和 SHA-512 哈希算法的 ECDSA
none不包含数字签名或 MAC 值

前端的实际操作方法

怎么存储

因为我比较喜欢使用 Cookie 来存储的,所以以 Cookie 为主。

封装方法

首先使用一个 npm 包,js-cookie。

npm install js-cookie -S

在合适的文件夹中创建一个 js 文件。一般推荐在utils文件夹下

import Cookies from "js-cookie";

const TokenName = "XXXXXXXX";

export function getToken() {
  return Cookies.get(TokenName);
}

export function setToken(token) {
  return Cookies.set(TokenName, token, {
    expires: 1,
    path: "/",
  });
}

export function removeToken() {
  return Cookies.remove(TokenName);
}

请求封装

以 VUE 来说,按照我之前关于 Axios 的文章,封装请求即可。

VUE.JS 请求工具 Axios 的封装

完结撒花🎉🎉🎉

打赏
上次编辑于: 2022/6/23 00:43:31
贡献者: ComicAuthor
评论
Powered by Waline v2.6.1