MST
星途 面试题库

面试题:TypeScript装饰器在复杂业务场景下权限验证的优化与设计

在一个大型企业级应用中,权限系统非常复杂,涉及到角色继承、数据范围权限等概念。例如,不同部门的管理员可能具有不同的数据范围权限。请基于TypeScript装饰器设计一个通用的权限验证框架,该框架需要具备高度的可扩展性和灵活性,能够适应未来可能的权限规则变化。请详细描述设计思路,并给出关键代码示例。
41.3万 热度难度
前端开发TypeScript

知识考点

AI 面试

面试题答案

一键面试

设计思路

  1. 定义权限验证装饰器:使用TypeScript装饰器语法,定义用于方法或类的权限验证装饰器。通过装饰器参数传递所需的权限信息。
  2. 权限规则存储与管理:创建一个模块来集中管理权限规则,比如可以用一个对象或数据库来存储角色与权限的对应关系、数据范围权限等。
  3. 上下文获取:在权限验证过程中,需要获取当前用户的角色、数据范围等上下文信息。可以通过全局状态管理(如Redux等)或者在请求上下文中传递。
  4. 可扩展性:设计的框架应易于添加新的权限验证逻辑,例如新的角色继承规则或数据范围验证方式,通过模块化设计和接口抽象来实现。

关键代码示例

  1. 定义权限验证装饰器
// 权限验证装饰器
function checkPermissions(requiredPermissions: string[]) {
    return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
        const originalMethod = descriptor.value;
        descriptor.value = function (...args: any[]) {
            // 这里模拟获取当前用户的权限
            const currentUserPermissions = getCurrentUserPermissions();
            const hasPermissions = requiredPermissions.every(permission => currentUserPermissions.includes(permission));
            if (hasPermissions) {
                return originalMethod.apply(this, args);
            } else {
                throw new Error('没有足够的权限');
            }
        };
        return descriptor;
    };
}

// 模拟获取当前用户权限的函数
function getCurrentUserPermissions(): string[] {
    // 实际应用中从上下文或全局状态获取
    return ['read:data', 'write:data'];
}
  1. 使用装饰器
class DataService {
    @checkPermissions(['read:data'])
    readData() {
        console.log('读取数据');
    }

    @checkPermissions(['write:data'])
    writeData() {
        console.log('写入数据');
    }
}

const dataService = new DataService();
dataService.readData();
// dataService.writeData(); // 可能会抛出权限不足的错误
  1. 数据范围权限示例
// 数据范围权限装饰器
function checkDataScope(dataScope: string) {
    return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
        const originalMethod = descriptor.value;
        descriptor.value = function (...args: any[]) {
            // 模拟获取当前用户的数据范围
            const currentUserDataScope = getCurrentUserDataScope();
            if (currentUserDataScope === dataScope) {
                return originalMethod.apply(this, args);
            } else {
                throw new Error('没有权限访问此数据范围');
            }
        };
        return descriptor;
    };
}

// 模拟获取当前用户数据范围的函数
function getCurrentUserDataScope(): string {
    // 实际应用中从上下文或全局状态获取
    return 'department1';
}

class DepartmentDataService {
    @checkDataScope('department1')
    accessDepartmentData() {
        console.log('访问部门1的数据');
    }
}

const departmentDataService = new DepartmentDataService();
departmentDataService.accessDepartmentData();