一. 简介
管理系统可不是谁都能对里面的数据进行操作,只能有权限的管理员才能进行相应的操作。
以下文章都是在 文章一 的基础上编写,所以一些基础的配置,就不再赘述,直接上手写重要代码。接下来就会通过最近自己在写的博客的后台管理系统(下文简称:管理系统),来对 中间件 + 登录
这个功能进行记载;本案例采用的是Restful API的方式给前端返回数据。
本实例用到的插件:mysql2 + egg-sequelize + egg-cors + egg-jwt + md5
。
二. 编码
1. Egg 后端
1.1. 登录鉴权方案
目前登录鉴权方案有很多,介绍可参考 常见登录鉴权方案 ,以下列出几种:
-
HTTP Auth Authentication
-
Cookie + Session
-
JWT
-
OAuth 本示例中则使用的是JWT的方式,所用到的插件为
egg-jwt
。 -
安装:
npm install egg-jwt --save
-
引入egg-jwt包:
// config/plugin.js 'use strict'; module.exports = { ... jwt: { enable: true, package: 'egg-jwt' } };
-
配置:
// config/config.default.js 'use strict'; module.exports = appInfo => { const config = exports = {}; ... config.cluster = { listen: { port: 1598, }, }; config.jwt = { secret: 'ea86dg645sdfg6sf', // 可自行定义 }; return { ...config }; };
-
使用
// app/controller/auth.js 'use strict'; const md5 = require('md5') const Controller = require('./base'); class AuthController extends Controller { async login() { const { ctx, service } = this const { username, password } = ctx.request.body const md5pwd = md5(password) const where = { username, password: md5pwd }; const result = await service.auth.login({ where }) this.success(result) } async getUserInfo() { const { ctx, service } = this const { token } = ctx.request.query const userinfo = await service.auth.getUserInfo(token) this.success(userinfo) } } module.exports = AuthController;
// app/service/auth.js 'use strict'; const Service = require('./base'); class AuthService extends Service { async login(option) { const { ctx, app } = this; const { count, rows } = await this._findAll('Users', option); const userInfo = rows[0]; if (count === 1) { return app.jwt.sign({ id: userInfo.id, username: userInfo.username, password: userInfo.password, }, app.config.jwt.secret, { expiresIn: '12h' }); } ctx.throw(403, '账号或密码错误'); } async getUserInfo(token) { const { ctx } = this; // 解密token const decoded = ctx.app.jwt.verify(token, ctx.app.config.jwt.secret); return await this._findById('Users', decoded.id); } } module.exports = AuthService;
1.2. 中间件的使用
从 官网 可得知,Egg 中间件
有三种使用方式:在应用中使用中间件
、在框架和插件中使用中间件
、 router 中使用中间件
,在不同场景下可选择不同的方式,在本案例中选择了 router 中使用中间件
。
-
写法
在管理系统中,除登录以外的接口,都需要有权限才能请求,所以在middleware
文件夹中定义中间件文件。如 jwt.js,并实现自定义的功能。// middleware/jwt.js // 在 “router 中使用中间件” 中用不到 const whiteList = ['/login'] module.exports = (options) => { return async function (ctx, next) { //判断接口路径是否在白名单(在 “router 中使用中间件”中不需要验证这一步) const isInWhiteList = whiteList.some(item => item == ctx.request.url) if (!isInWhiteList) { // 拿到前端传过来的 token const token = ctx.request.header.authorization if (token) { //解密token const secret = ctx.app.config.jwt.secret const decoded = ctx.app.jwt.verify(token, secret) || 'false' if (decoded !== 'false') { await next() } else { ctx.throw(403, '无效Token') } } else { ctx.throw(403, '无Token') } } else { await next() } } }
-
使用
// router.js 'use strict'; module.exports = app => { const { router, controller, middleware } = app; // 引入 const jwt = middleware.jwt(app.config.jwt); // 用户登录、获取用户信息 router.post('/admin/login', controller.auth.login); router.get('/admin/getUserInfo', jwt, controller.auth.getUserInfo); // 文章管理 router.get('/admin/article',jwt, controller.article.index); router.get('/admin/article/findById',jwt, controller.article.findById); router.post('/admin/article/doAdd',jwt, controller.article.doAdd); router.put('/admin/article/doEdit',jwt, controller.article.doEdit); router.delete('/admin/article/doDel',jwt, controller.article.doDel); };
2. Vue 前端
本文主要是讲述Egg中间件的使用。这里只简单说一下前端怎么做:
- 请求登录接口,将登陆成功后返回的token信息,存入到本地缓存中;
- 在需要鉴权的接口请求时,将token放入请求头中一并返回给后端做鉴权;
- 处理后端返回的信息(成功或者失败)。
三. 总结(router 中使用中间件)
第一步: 自定义中间件。在 middleware
文件夹中定义中间件文件,如 jwt.js;
第二步: 使用中间件。在 router.js
中,先引入,再调用;
第三步: 前端使用。