本文主要是介绍写一个eggjs权限验证中间件,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
关于中间件
中间件(Middleware) - 为企业级框架和应用而生
官方文档说的很清楚了,不再叙述。
我们要达到怎么样一个效果?
- 用户没有登录不能访问一些特定的页面,比如修改密码、修改资料啊这些敏感操作。如果用户没有登录访问这些页面会自动跳转到登录页面让用户登录。
- 如果用户登录过了就可以访问这些页面(验证通过。)
- 没有登录可以访问登录页面来进行登陆,或者注册等不需要权限的页面。
如果不使用中间件你会怎么写
在controller/user 修改密码,
async changePassword(){if (this.ctx.session.userId) { // 如果有这个session// 执行修改密码} else {// 不写就没有响应,会404ctx.redirect('/login');}
}
然后修改资料
async changeUserInfo(){if (this.ctx.session.userId) { // 如果有这个session// 执行修改资料} else {// 不写就没有响应,会404ctx.redirect('/login');}
}
然后登录就不用判断
async login(){let {userName, password} = this.ctx.request,body;// 校验密码let userFind = this.service.findOne({userName, password});// 获取user信息if (userFind) {this.ctx.session.userId = userFind._id;// 返回成功this.ctx.body = '登录成功';} else {this.ctx.body = '登录失败,账号密码错误';}
}
这样如果代码量小的话也能接受,但是如果将来接口越来越多,需要检验权限的地方也越来越多,修改就会很麻烦。
剥离出来,自成体系
在app/middleware下面新建authLogin.js文件用来判断是否登录
module.exports = (options, app) => {return async function testMiddleware(ctx, next) {let whiteUrls = options.whiteUrls || [];// 如果ctx.url在白名单中let isWhiteUrl = whiteUrls.some((whiteUrl)=> ctx.url.startsWith(whiteUrl));if (! isWhiteUrl) {console.log('authLogin');if (! ctx.session.userId) {ctx.redirect('/login'); // 让用户去登录}else {console.log('auth ok');await next();}} else {// 白名单console.log('white url');await next();}};
};
在controller/user 修改密码,
async changePassword(){//不需要判断,直接执行修改密码
}
然后修改资料
async changeUserInfo(){//不需要判断,直接执行修改资料
}
然后登录还是一样
async login(){let {userName, password} = this.ctx.request,body;// 校验密码let userFind = this.service.findOne({userName, password});// 获取user信息if (userFind) {this.ctx.session.userId = userFind._id;// 返回成功this.ctx.body = '登录成功';} else {this.ctx.body = '登录失败,账号密码错误';}
}
代码是不是精简清爽多了呢?
注意的几个点,
- 要加到config的middleware列表里面:
config.middleware = [''authLogin'];
- await next()要放在最后,这样意味着校验规则会在路由匹配之前执行。
- whiteUrl是在config.default.js中的options配置,也可以不要这个,直接使用match或者ignore(相关规则参考官方文档关于中间件这一块)
config.authLogin = {whiteUrls: ['/test'], // 是使用url的前缀匹配的// 不需要登录的页面,白名单URL// 也可以使用ignore: ['/login', '/register', '/doLogin', '/doRegister']// 使用 match是限制只在这几个页面执行// match和ignore不能同时使用};
- 不配置 config.authLogin的话呢?只在特定路由中使用:
router.get('/login', authLogin, controller.user.login);
这篇关于写一个eggjs权限验证中间件的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!