基于传统的 cookie 、session 认证的一些问题
-
session 一般存储在应用的内存中,随着用户数量增加,服务端内存开销也比较大【这里也推荐使用 redis】
-
如果是分布式服务应用,想要共享数据还得有一台中央服务器,这样会限制负载均衡的能力
-
CSRF【跨站请求伪造】,只要截获 cookie ,用户信息很容易暴露
-
再一个问题是,cookie 是可以在浏览器端设置的,一旦用户不小心禁用了 cookie ,那他可能再也登录不了系统了。
基于 token 的鉴权
token 的鉴权类似于 http 协议也是无状态的,它不需要服务端去保留用户的认证信息
JWT
JWT 是由三段信息构成 :
-
头部基本信息
// 一般头部像是这样 { 'typ': 'JWT', // 声明类型,这里是 jwt 'alg': 'HS256' // 声明加密的算法 }
-
载荷(payload)
主要的信息都在这里【 分为 预定义选项 和 自定义选项 】
/* 预定义信息 iss: 该 JWT 的签发者 sub: 该 JWT 所面向的用户 aud: 接收 JWT 的一方 exp: 过期时间,这个过期时间必须要大于签发时间,Unix时间戳 iat: 签发时间 nbf: 定义在什么时间之前,该jwt都是不可用的 jti: jwt的唯一身份标识 */ { iss: "龙龙老表", msg:"my lover" }
-
签名
// 前面的 header 和 payload 分别进行 base64 加密,中间通过 . 点连接【当然是可以在客户端解密的,属于明文部分】 let encodedString = base64UrlEncode(header) + "." + base64UrlEncode(payload); // 通过算法将 加密之后合并的 前两部分 跟一个自定义字符串密匙【这个密钥是关键,不可以告诉任何人】 组合,形成最终的签名 let signature = HMACSHA256(encodedString, "secret");
- secret 这个字符串 就是用来进行 jwt 的签发和 jwt 的验证,所以,它是服务端的私钥
具体代码
服务端
const http = require("http");
const fs = require("fs");
const jwt = require("jsonwebtoken");
let secret = "mytoken"; // 密钥
// 获取 post 数据
function getPostData(req) {
return new Promise((resolve, reject) => {
let resStr = "";
req.on("data", (chunk) => {
resStr += chunk;
});
req.on("end", () => {
resolve(resStr);
});
});
}
http
.createServer((req, res) =>