一、媒介
JWT(JSON Web Token),是为了在收集环境间通报声明而实行的一种基于JSON的开放规范(RFC 7519)。
JWT不是一个新颖的东西,网上相干的引见已异常多了。不是很相识的能够在网上搜刮一下相干信息。
同步到sau交流学习社区:https://www.mwcxs.top/page/45…
二、源码
Talk is cheap. Show me the code.
三、事情流程
JWT实质来讲是一个token。在前后端举行HTTP衔接时来举行响应的考证。
- 博客的背景治理体系提议登录要求,后端服务器校验胜利以后,天生JWT认证信息;
- 前端接收到JWT后举行存储;
- 前端在以后每次接口挪用提议HTTP要求时,会将JWT放到HTTP的headers参数里的authorization中一起发送给后端;
- 后端接收到要求时会依据JWT中的信息来校验当前提议HTTP要求的用户是不是是具有接见权限的,有接见权限时则交给服务器继承处置惩罚,没偶然则直接返回401毛病。
四、完成历程
1. 登录胜利天生JWT
申明:以下代码只保留了中心代码,细致代码可在对应文件中检察,下同。
// /server/api/admin/admin.controller.js
const jwt = require('jsonwebtoken');
const config = require('../../config/config');
exports.login = async(ctx) => {
// ...
if (hashedPassword === hashPassword) {
// ...
// 用户token
const userToken = {
name: userName,
id: results[0].id
};
// 签发token
const token = jwt.sign(userToken, config.tokenSecret, { expiresIn: '2h' });
// ...
}
// ...
}
2. 增加中间件校验JWT
// /server/middlreware/tokenError.js
const jwt = require('jsonwebtoken');
const config = require('../config/config');
const util = require('util');
const verify = util.promisify(jwt.verify);
/**
* 推断token是不是可用
*/
module.exports = function () {
return async function (ctx, next) {
try {
// 猎取jwt
const token = ctx.header.authorization;
if (token) {
try {
// 解密payload,猎取用户名和ID
let payload = await verify(token.split(' ')[1], config.tokenSecret);
ctx.user = {
name: payload.name,
id: payload.id
};
} catch (err) {
console.log('token verify fail: ', err)
}
}
await next();
} catch (err) {
if (err.status === 401) {
ctx.status = 401;
ctx.body = {
success: 0,
message: '认证失利'
};
} else {
err.status = 404;
ctx.body = {
success: 0,
message: '404'
};
}
}
}
}
3. Koa.js中增加JWT处置惩罚
此处在开辟时须要过滤掉登录接口(login),否则会致使JWT考证永久失利。
// /server/config/koa.js
const jwt = require('koa-jwt');
const tokenError = require('../middlreware/tokenError');
// ...
const app = new Koa();
app.use(tokenError());
app.use(bodyParser());
app.use(koaJson());
app.use(resource(path.join(config.root, config.appPath)));
app.use(jwt({
secret: config.tokenSecret
}).unless({
path: [/^\/backapi\/admin\/login/, /^\/blogapi\//]
}));
module.exports = app;
4.前端处置惩罚
前端开辟运用的是Vue.js,发送HTTP要求运用的是axios。
(1) 登录胜利以后将JWT存储到localStorage中(可依据个人须要存储,我个人是比较喜好存储到localStorage中)。
methods: {
login: async function () {
// ...
let res = await api.login(this.userName, this.password);
if (res.success === 1) {
this.errMsg = '';
localStorage.setItem('SONG_EAGLE_TOKEN', res.token);
this.$router.push({ path: '/postlist' });
} else {
this.errMsg = res.message;
}
}
}
(2) Vue.js的router(路由)跳转前校验JWT是不是存在,不存在则跳转到登录页面。
// /src/router/index.js
router.beforeEach((to, from, next) => {
if (to.meta.requireAuth) {
const token = localStorage.getItem('SONG_EAGLE_TOKEN');
if (token && token !== 'null') {
next();
} else {
next('/login');
}
} else {
next();
}
});
(3) axios拦截器中给HTTP一致增加Authorization信息
// /src/api/config.js
axios.interceptors.request.use(
config => {
const token = localStorage.getItem('SONG_EAGLE_TOKEN');
if (token) {
// Bearer是JWT的认证头部信息
config.headers.common['Authorization'] = 'Bearer ' + token;
}
return config;
},
error => {
return Promise.reject(error);
}
);
(4)axios拦截器在接收到HTTP返回时一致处置惩罚返回状况
// /src/main.js
axios.interceptors.response.use(
response => {
return response;
},
error => {
if (error.response.status === 401) {
Vue.prototype.$msgBox.showMsgBox({
title: '毛病提醒',
content: '您的登录信息已失效,请从新登录',
isShowCancelBtn: false
}).then((val) => {
router.push('/login');
}).catch(() => {
console.log('cancel');
});
} else {
Vue.prototype.$message.showMessage({
type: 'error',
content: '体系涌现毛病'
});
}
return Promise.reject(error);
}
);
五、总结
这个基本上就是JWT的流程。固然纯真的JWT并不是说相对平安的,不过关于一个个人博客体系的认证来讲照样充足的。
末了打个小广告。现在正在开辟新版的个人博客中,包含两部分:
【前端】(https://github.com/saucxs/son…
【后端】(https://github.com/saucxs/son…
都已在GitHub上开源,现在在逐步完善功用中。迎接感兴趣的同砚fork和star。