设计思路
- 定义角色类型:首先定义表示不同用户角色的类型,如
Admin
和User
。
- 使用元数据:利用TypeScript的
reflect - metadata
库来存储和读取方法的权限元数据。在类装饰器和方法装饰器中使用元数据来标记方法允许的角色。
- 类装饰器:创建一个类装饰器,它将遍历类的所有方法,并使用方法装饰器标记每个方法的权限。
- 方法装饰器:定义方法装饰器,用来标记哪些角色可以访问该方法。
- 权限验证函数:编写一个函数,在调用方法前验证当前用户角色是否有权限访问该方法。
关键TypeScript代码实现
import 'reflect - metadata';
// 定义角色类型
type Role = 'Admin' | 'User';
// 方法装饰器,用于标记哪些角色可以访问该方法
function allow(roles: Role[]) {
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
Reflect.defineMetadata('allowedRoles', roles, target, propertyKey);
return descriptor;
};
}
// 类装饰器,用于为类的所有方法应用权限控制
function applyPermissions(target: Function) {
const prototype = target.prototype;
for (const propertyKey in prototype) {
if (typeof prototype[propertyKey] === 'function') {
if (!Reflect.hasMetadata('allowedRoles', prototype, propertyKey)) {
// 如果没有显式标记,则默认只有Admin可以访问
allow(['Admin'])(prototype, propertyKey, prototype[propertyKey]);
}
}
}
return target;
}
// 权限验证函数
function checkPermission(target: any, propertyKey: string, role: Role) {
const allowedRoles = Reflect.getMetadata('allowedRoles', target, propertyKey);
return allowedRoles.includes(role);
}
// 示例类
@applyPermissions
class MyService {
@allow(['User', 'Admin'])
public publicMethod() {
console.log('This is a public method.');
}
private privateMethod() {
console.log('This is a private method.');
}
}
// 模拟调用
const myService = new MyService();
const userRole: Role = 'User';
if (checkPermission(myService, 'publicMethod', userRole)) {
myService.publicMethod();
} else {
console.log('You do not have permission to access this method.');
}