egg-jwt+自定义权限认证中间件 实现跨域配置

658 阅读2分钟

跨域配置文件

代码演示

config.default.js

/**
 * config:配置各个环境下插件自身的默认配置项
 * 
 * 所有框架、插件和应用级别的配置都可以通过 Config 对象获取到
 * 
 * 通过 app.config 从 Application 实例上获取到 config 对象,也可以在 Controller, Service, Helper 的实例上通过 this.config 获取到 config 对象
 * 
 * config.default.js 为默认的配置文件,所有环境都会加载这个配置文件,一般也会作为开发环境的默认配置文件。
 * 
 * 配置加载顺序(优先级)  应用 > 框架 > 插件
 */

/* eslint valid-jsdoc: "off" */

'use strict';

const os = require('os');
//获取本机ip
function getIpAddress() {
     /**os.networkInterfaces() 返回一个对象,该对象包含已分配了网络地址的网络接口 */
  var interfaces = os.networkInterfaces();
    for (var devName in interfaces) {
      var iface = interfaces[devName];
       for (var i = 0; i < iface.length; i++) {
              var alias = iface[i];
                if (alias.family === 'IPv4' && alias.address !== '127.0.0.1' && !alias.internal) {
                  return alias.address;
                }
          }
     }
}
const myHost = getIpAddress();
console.log(myHost);
/**
 * @param {Egg.EggAppInfo} appInfo app info
 */
module.exports = appInfo => {
  /**
   * built-in config
   * @type {Egg.EggAppConfig}
   **/
  const config = exports = {};

  // add your middleware config here
  config.middleware = ['authorization'];
  // 中间件匹配路由
  // 开启中间件,登录页不需要权限认证
  config.authorization = {
    enable: true,
    ignore: '/user/login' // 只忽略指定路由,可以用ignore
  };

  //配置端口信息
  config.cluster = {
    listen:{
      port:7001,
      hostname:myHost
    }
  };

  //配置跨域
  config.security = {
    csrf: {
      // 前后端分离,post请求不方便携带_csrf
      enable: false,
      ignoreJSON: true
    },
    //配置白名单
    domainWhiteList: [`http://${myHost}:7001`]
  };

  config.jwt = {
    //密钥:自己设置的值
    secret: "milk" 
  }

  //配置数据库
  config.sequelize = {
    dialect: 'mysql',
    host: '127.0.0.1',
    port: 3306,
    database: 'milk', // 数据库名
    username: 'root', // 数据库账号
    password: 'root', // 数据库密码
    timezone: '+08:00', //保存为本地时区
    dialectOptions: { //读取时用的时间
      dateStrings: true,
      typeCast(field, next) {
        // for reading from database
        if(field.type === "DATETIME") {
          return field.string();
        }
        return next();
      }
    },
    define: {
      freezeTableName: true,
      timestamps: false,
      //解决中文输入问题
      charset: 'utf8mb4'
    },
    app: true
  };

  return {
    ...config
  };
};

这里的 config.authorization 也可以这样配置

// 可以让authorization中间件关闭,当match到指定路由时,才开启token验证!
config.authorization = {
        enable: false, // 是否开启中间件,默认开启
        match(ctx) { // 只匹配指定路由,反之如果只忽略指定路由,可以用ignore
            //匹配不需要验证token的路由
            const url = ctx.request.url;
            if (url.startsWith('/base')) {
                return false;
            } else {
                return true; // 开启中间件,开启token验证
            }
        }
};

配置跨域那部分也可以这样配置,前提是安装了egg-cors

// 配置跨域
config.security = {
  csrf: {
    enable: false, // 前后端分离,post请求不方便携带_csrf
    ignoreJSON: true
  },
  domainWhiteList: [`http://${myHost}:7001`, 'http://192.168.xx.xxx:8080'] // 配置白名单  第一个服务端网址,第二个客户端网址
}

config.cors = {
  origin: '*', //允许所有跨域访问,注释掉则只允许上面 白名单 访问,建议不要注释掉
  allowMethods: 'GET,HEAD,PUT,POST,DELETE,PATCH'
}
  
config.jwt = {
  secret: 'milk' // 自定义值
}

权限认证中间件文件目录

在这里插入图片描述

代码演示

authorization.js
利用egg-jwt解析客户端携带过来的token,认证是否是当前用户

module.exports = () => {
    return async function(ctx, next) {
        if(ctx.get('Authorization')) {
            // console.log(ctx.get('Authorization'))
            let token = ctx.get('Authorization');
            try {
                ctx.app.jwt.verify(token, ctx.app.config.jwt.secret);
            } catch (error) {
                if(error.name == 'TokenExpiredError') {
                    /**401 http错误 未经授权,访问由于凭证无效而被拒绝 */
                    ctx.status = 401;
                    ctx.body = {
                        msg: 'token过期'
                    }
                    return;
                } else {
                    ctx.status = 401;
                    ctx.body = {
                        msg: 'token失效'
                    }
                    return;
                }
            }
            await next();
        } else {
            ctx.status = 401;
            ctx.body = {
                msg: 'no token detected in http header Authorization'
            }
            return;
        }
    }
}