NodeJs基于Token的身份认证
传统的 Session 验证
起初的验证方式是存在于服务器的,用户登录进来以后,服务器判断成功,将数据存进 session 里面,向用户返回一个 sessionID。这样的弊端是,假如用户基数特别大,每登录一个用户,就要存储一条,对服务器的内存压力比较大。
基于 Token 的验证方法
基于 Token 的验证方法是无状态的,因此我们就不用把信息存在服务器中了。
Token 可以通过请求头传输,所以他可以在任何一种 http 请求中被发送到服务器中。
Token 的验证流程
客户端发送用户、密码到服务器。
服务器接收到信息之后和数据库进行比对,验证成功后,生成一段有时效的Token字符串,向客户端返回登陆成功信息以及Token字符串。
客服端接收到信息,将Token存储在Local Storage或者Cookies中。
客服端再向服务器发送请求时,将Token放在请求头中。
服务器先解析请求头中的Token,如果解析成功,那么就进入业务逻辑中,如果不成功返回错误信息。
nodeJS(express) + jwt(jsonwebtoken)
首先安装 jsonwebtoken
[tag type="primary" outline]npm install jsonwebtoken -S[/tag]
然后在服务器中创建一个 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] ==> 使用相同的解密方式
具体参数
可以查看jsonwebtoken在 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。
[tag type="primary" outline]npm install js-cookie -S[/tag]
在合适的文件夹中创建一个 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 的文章,封装请求即可。