nodejs的jwt实现
JWT
JSON Web Token(JSON Web令牌)
是一个开放标准(rfc7519),它定义了一种紧凑的、自包含的方式,用于在各方之间以JSON对象安全地传输信息。此信息可以验证和信任,因为它是数字签名的。jwt可以使用秘密〈使用HNAC算法)或使用RSA或ECDSA的公钥/私钥对进行签名。
通过JSON形式作为Web应用中的令牌,用于在各方之间安全地将信息作为JSON对象传输。在数据传输过程中还可以完成数据加密、签名等相关处理。
JWT作用:
授权:一旦用户登录,每个后续请求将包括JWT,从而允许用户访问该令牌允许的路由,服务和资源。它的开销很小并且可以在不同的域中使用。如:单点登录。
信息交换:在各方之间安全地传输信息。JWT可进行签名(如使用公钥/私钥对),因此可确保发件人。由于签名是使用标头和有效负载计算的,因此还可验证内容是否被篡改。
JWT结构
就是令牌token,是一个String字符串,由3部分组成,中间用点隔开
令牌组成:
标头(Header)
有效载荷(Payload)
签名(Signature)
token格式:head.payload.singurater 如:xxxxx.yyyy.zzzz
案例
以下做一个简单的token签名,前端使用vue,服务器使用nodejs
功能实现,两个页面,一个登录页一个列表页,登录后返回加密token,访问列表页时需要token校验,如果校验不通过返回登录页,通过展示列表页
nodejs实现
app.js
const express = require("express");
const app = express();
const bosyParser = require("body-parser");
const jwt = require("jsonwebtoken"); //加载包
app.use(bosyParser.json()); //解析json数据
//跨域
app.use(function (req, res, next) {
//设置允许跨域的域名,*代表允许任意域名跨域
res.header("Access-Control-Allow-Origin", "*");
// 例如 允许百度跨域, 把上面这行的*替换为 https://baidu.com
//允许的header类型
res.header("Access-Control-Allow-Headers", "content-type");
//跨域允许的请求方式
res.header("Access-Control-Allow-Methods", "DELETE,PUT,POST,GET,OPTIONS");
if (req.method.toLowerCase() == "options") {
res.sendStatus(200); //让options预验证尝试请求快速结束
}
next();
});
const user = { name: "zhangsan", password: "123456" }; //储存账号,模拟数据库
const theKey = "mykey";//定义密匙
//登录
app.post("/login", (req, res) => {
if (JSON.stringify(user) === JSON.stringify(req.body)) {
let token = jwt.sign(user.name, theKey);//生成token
//账号密码正确
res.json({ code: 0, token, data: user });
} else {
res.json({ code: 1, data: "账号或密码错误" });
}
});
//中间件,校验token
let autoCheck = (req, res, next) => {
const token =
req.headers.authorization && req.headers.authorization.split(" ")[1];
if (token) {
req.token = token;
next();
} else {
res.json("token失效");
}
};
//获取列表数据
app.get("/list", autoCheck, (req, res) => {
const token = req.token;
jwt.verify(token, theKey, (err, data) => {
//data为解码之后的数据,即name
if (!err) {
res.json({ code: 0, data });
} else {
res.json({ code: 1, data: "token签名错误" });
}
});
});
app.listen(4000, () => {
console.log("4000端口启动了");
});
axios添加拦截,方便操作
import axios from "axios"; //添加请求拦截,设置authorization axios.interceptors.request.use( (config) => { const token = sessionStorage.getItem("token"); if (token) { //每次请求尝试携带token config.headers.Authorization = `Bearer ${token}`; } return config; }, (err) => { return Promise.reject(err); } ); //添加响应拦截 axios.interceptors.response.use((res) => { if (res.data.code === 0) { //响应数据减少一层 return Promise.resolve(res.data); } else { return Promise.reject("请求失败"); } }); export default axios;
两个页面
login.vue
submit() { this.$axios.post('/api/login', this.user).then( (res) => { if (res.code === 0) { const { data, token } = res token && sessionStorage.setItem('token', token)//保存token data && this.$router.push('/list') } }, (err) => { console.log(err) } ) }
此处提交url:/api/login使用了代理
list.vue
mounted() { this.$axios.get('/api/list').then( (res) => { if (res.code === 0) { this.user.name = res.data } }, (err) => { console.log(err) this.$router.push('/login') } ) }
token在axios中设置了,此次不需要携带token
一个简单的登录验证token就实现了。

浙公网安备 33010602011771号