You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
vue-shop-admin-work/modules/authorization.js

91 lines
5.0 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

// 引入Node.js的path模块用于处理文件路径相关操作
var path = require('path');
// 原本要引入的roles控制器模块此处被注释掉了可能后续会按需启用
// var roles_controller = require("../controllers/roles");
// 再次引入path模块前面的引入语句重复了但在Node.js中不会有实质影响可考虑优化掉重复引入的情况
var path = require("path");
// 创建一个全局对象service_caches用于缓存服务相关的模块或数据初始为空对象
global.service_caches = {};
// 创建一个全局变量service_auth_fn用于存储全局验证函数初始值为null
global.service_auth_fn = null;
/**
* Invocation函数用于构造一个回调对象格式主要用于在调用服务的具体方法时进行权限验证等相关操作。
*
* @param {[type]} serviceName 服务名称,用于标识具体是哪个服务。
* @param {[type]} actionName 动作名称(方法名),对应服务模块里具体的函数名称。
* @param {[type]} serviceModule 服务模块即通过require加载进来的包含具体业务逻辑函数的模块对象。
* @param {[type]} origFunc 原始方法,也就是服务模块里未经包装的原始业务逻辑函数。
*/
function Invocation(serviceName, actionName, serviceModule, origFunc) {
// 返回一个新的函数,这个函数会接收一些参数(此处未在形参中体现,在调用时会传入),并返回另一个函数作为真正的回调函数
return function () {
var origArguments = arguments;
return function (req, res, next) {
// 判断全局验证函数是否存在,如果存在则进行权限验证流程
if (global.service_auth_fn) {
global.service_auth_fn(req, res, next, serviceName, actionName, function (pass) {
// 如果权限验证通过pass为true则执行原始的业务逻辑函数
if (pass) {
origFunc.apply(serviceModule, origArguments);
} else {
// 如果权限验证失败向客户端返回相应的错误信息状态码为401表示未授权
res.sendResult(null, 401, "权限验证失败");
}
});
} else {
// 如果全局验证函数不存在,直接返回权限验证失败的错误信息给客户端
res.sendResult(null, 401, "权限验证失败");
}
}
}
}
// 定义一个函数用于获取服务对象,它是模块对外暴露的接口之一
module.exports.getService = function (serviceName) {
// 先检查全局缓存中是否已经存在指定名称的服务对象,如果存在则直接返回缓存中的服务对象
if (global.service_caches[serviceName]) {
return global.service_caches[serviceName];
}
// 构建服务模块的文件路径,通过拼接当前工作目录、"services"文件夹以及服务名称来确定具体路径
var servicePath = path.join(process.cwd(), "services", serviceName);
// 通过require加载对应的服务模块如果模块不存在则返回null并在控制台打印提示信息
var serviceModule = require(servicePath);
if (!serviceModule) {
console.log("模块没有被发现");
return null;
}
// 在全局缓存对象中为当前服务名称创建一个空对象,用于后续存储该服务的具体方法相关的回调对象等信息
global.service_caches[serviceName] = {};
// 打印一些提示信息,表明正在拦截指定名称的服务,方便调试和查看流程
console.log("*****************************************");
console.log("拦截服务 => %s", serviceName);
console.log("*****************************************");
// 遍历服务模块里的所有属性(通常是方法)
for (actionName in serviceModule) {
// 检查属性对应的是否是一个函数(即服务模块里有效的业务逻辑函数)
if (serviceModule && serviceModule[actionName] && typeof (serviceModule[actionName]) == "function") {
var origFunc = serviceModule[actionName];
// 使用Invocation函数构造该方法对应的回调对象并将其存储到全局缓存对象中对应的服务和方法名下
global.service_caches[serviceName][actionName] = Invocation(serviceName, actionName, serviceModule, origFunc);
console.log("action => %s", actionName);
}
}
// 打印一些分割线和空行,用于在控制台输出中更清晰地区分不同服务的处理情况,此处注释掉了打印全局缓存对象的语句
// console.log(global.service_caches);
console.log("*****************************************\n");
return global.service_caches[serviceName];
}
// 定义一个函数用于设置全局验证函数,它也是模块对外暴露的接口,供外部传入具体的验证函数
module.exports.setAuthFn = function (authFn) {
global.service_auth_fn = authFn;
}