写一个eggjs权限验证中间件 - 前端劝退师

写一个eggjs权限验证中间件

作者: 前端劝退师

全网最懒博主

手机扫码查看

标签:

特别声明:文章多为网络转载,资源使用一般不提供任何帮助,特殊资源除外,如有侵权请联系!

关于中间件

https://eggjs.org/zh-cn/basics/middleware.html
官方文档说的很清楚了,不再叙述。

我们要达到怎么样一个效果?

  1. 用户没有登录不能访问一些特定的页面,比如修改密码、修改资料啊这些敏感操作。如果用户没有登录访问这些页面会自动跳转到登录页面让用户登录。
  2. 如果用户登录过了就可以访问这些页面(验证通过。)
  3. 没有登录可以访问登录页面来进行登陆,或者注册等不需要权限的页面。

如果不使用中间件你会怎么写

在controller/user 修改密码,

async changePassword(){
    if (this.ctx.session.userId) {  // 如果有这个session
        // 执行修改密码
   } else {
     // 不写就没有响应,会404
     ctx.redirect('/login');
   }
}

然后修改资料

async changeUserInfo(){
    if (this.ctx.session.userId) {  // 如果有这个session
        // 执行修改资料
   } else {
    // 不写就没有响应,会404
    ctx.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 = '登录失败,账号密码错误';
    }
}

代码是不是精简清爽多了呢?

注意的几个点,

  1. 要加到config的middleware列表里面:
  config.middleware = [''authLogin'];
  1. await next()要放在最后,这样意味着校验规则会在路由匹配之前执行。
  2. whiteUrl是在config.default.js中的options配置,也可以不要这个,直接使用match或者ignore(相关规则参考官方文档关于中间件这一块)
  config.authLogin = {
    whiteUrls: ['/test'], // 是使用url的前缀匹配的
    // 不需要登录的页面,白名单URL
    // 也可以使用
    ignore: ['/login', '/register', '/doLogin', '/doRegister']

    // 使用 match是限制只在这几个页面执行
    // match和ignore不能同时使用
  };
  1. 不配置 config.authLogin的话呢?只在特定路由中使用:
  router.get('/login', authLogin, controller.user.login);
分享到:
打赏
未经允许不得转载:

作者: 前端劝退师, 转载或复制请以 超链接形式 并注明出处 前端劝退师
原文地址: 《写一个eggjs权限验证中间件》 发布于2020-2-16

切换注册

登录

您也可以使用第三方帐号快捷登录

切换登录

注册

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏