10.1 概述
权限管理与安全控制是低代码平台的核心安全保障,确保系统资源的安全访问和数据保护。本章将详细介绍如何构建一个完整的权限管理系统,包括用户认证、角色权限、资源访问控制、数据安全和审计日志等功能。
10.2 权限管理架构
10.2.1 权限管理器接口
// 权限管理器接口
interface PermissionManager {
// 用户管理
createUser(userInfo: CreateUserRequest): Promise<User>;
updateUser(userId: string, updates: UpdateUserRequest): Promise<User>;
deleteUser(userId: string): Promise<void>;
getUser(userId: string): Promise<User | null>;
queryUsers(query: UserQuery): Promise<User[]>;
// 角色管理
createRole(roleInfo: CreateRoleRequest): Promise<Role>;
updateRole(roleId: string, updates: UpdateRoleRequest): Promise<Role>;
deleteRole(roleId: string): Promise<void>;
getRole(roleId: string): Promise<Role | null>;
queryRoles(query: RoleQuery): Promise<Role[]>;
// 权限管理
createPermission(permissionInfo: CreatePermissionRequest): Promise<Permission>;
updatePermission(permissionId: string, updates: UpdatePermissionRequest): Promise<Permission>;
deletePermission(permissionId: string): Promise<void>;
getPermission(permissionId: string): Promise<Permission | null>;
queryPermissions(query: PermissionQuery): Promise<Permission[]>;
// 用户角色关联
assignRoleToUser(userId: string, roleId: string): Promise<void>;
removeRoleFromUser(userId: string, roleId: string): Promise<void>;
getUserRoles(userId: string): Promise<Role[]>;
// 角色权限关联
assignPermissionToRole(roleId: string, permissionId: string): Promise<void>;
removePermissionFromRole(roleId: string, permissionId: string): Promise<void>;
getRolePermissions(roleId: string): Promise<Permission[]>;
// 权限检查
hasPermission(userId: string, resource: string, action: string): Promise<boolean>;
checkPermission(userId: string, permission: PermissionCheck): Promise<boolean>;
getUserPermissions(userId: string): Promise<Permission[]>;
// 资源管理
registerResource(resource: ResourceDefinition): Promise<void>;
unregisterResource(resourceId: string): Promise<void>;
getResource(resourceId: string): Promise<ResourceDefinition | null>;
listResources(): Promise<ResourceDefinition[]>;
}
// 低代码权限管理器实现
class LowCodePermissionManager implements PermissionManager {
private users: Map<string, User> = new Map();
private roles: Map<string, Role> = new Map();
private permissions: Map<string, Permission> = new Map();
private resources: Map<string, ResourceDefinition> = new Map();
private userRoles: Map<string, Set<string>> = new Map();
private rolePermissions: Map<string, Set<string>> = new Map();
private eventBus: EventBus;
private auditLogger: AuditLogger;
private encryptionService: EncryptionService;
constructor(options: PermissionManagerOptions) {
this.eventBus = options.eventBus;
this.auditLogger = options.auditLogger;
this.encryptionService = options.encryptionService;
this.initializeDefaultData();
}
// 用户管理实现
async createUser(userInfo: CreateUserRequest): Promise<User> {
const userId = this.generateId();
const hashedPassword = await this.encryptionService.hashPassword(userInfo.password);
const user: User = {
id: userId,
username: userInfo.username,
email: userInfo.email,
displayName: userInfo.displayName,
avatar: userInfo.avatar,
status: 'active',
passwordHash: hashedPassword,
metadata: userInfo.metadata || {},
createdAt: new Date(),
updatedAt: new Date(),
lastLoginAt: null
};
this.users.set(userId, user);
// 记录审计日志
await this.auditLogger.log({
action: 'user:created',
userId: userId,
details: { username: user.username, email: user.email },
timestamp: new Date()
});
// 发送事件
this.eventBus.emit('user:created', { user });
return user;
}
async updateUser(userId: string, updates: UpdateUserRequest): Promise<User> {
const user = this.users.get(userId);
if (!user) {
throw new Error(`用户不存在: ${userId}`);
}
const updatedUser: User = {
...user,
...updates,
updatedAt: new Date()
};
// 如果更新密码,需要重新哈希
if (updates.password) {
updatedUser.passwordHash = await this.encryptionService.hashPassword(updates.password);
}
this.users.set(userId, updatedUser);
// 记录审计日志
await this.auditLogger.log({
action: 'user:updated',
userId: userId,
details: { updates },
timestamp: new Date()
});
// 发送事件
this.eventBus.emit('user:updated', { user: updatedUser, updates });
return updatedUser;
}
async deleteUser(userId: string): Promise<void> {
const user = this.users.get(userId);
if (!user) {
throw new Error(`用户不存在: ${userId}`);
}
// 删除用户角色关联
this.userRoles.delete(userId);
// 删除用户
this.users.delete(userId);
// 记录审计日志
await this.auditLogger.log({
action: 'user:deleted',
userId: userId,
details: { username: user.username },
timestamp: new Date()
});
// 发送事件
this.eventBus.emit('user:deleted', { userId, user });
}
async getUser(userId: string): Promise<User | null> {
return this.users.get(userId) || null;
}
async queryUsers(query: UserQuery): Promise<User[]> {
let users = Array.from(this.users.values());
// 应用过滤条件
if (query.status) {
users = users.filter(user => user.status === query.status);
}
if (query.search) {
const searchLower = query.search.toLowerCase();
users = users.filter(user =>
user.username.toLowerCase().includes(searchLower) ||
user.email.toLowerCase().includes(searchLower) ||
user.displayName?.toLowerCase().includes(searchLower)
);
}
// 应用排序
if (query.sortBy) {
users.sort((a, b) => {
const aValue = a[query.sortBy as keyof User];
const bValue = b[query.sortBy as keyof User];
const order = query.sortOrder === 'desc' ? -1 : 1;
if (aValue < bValue) return -1 * order;
if (aValue > bValue) return 1 * order;
return 0;
});
}
// 应用分页
const offset = ((query.page || 1) - 1) * (query.limit || 10);
const limit = query.limit || 10;
return users.slice(offset, offset + limit);
}
// 角色管理实现
async createRole(roleInfo: CreateRoleRequest): Promise<Role> {
const roleId = this.generateId();
const role: Role = {
id: roleId,
name: roleInfo.name,
description: roleInfo.description,
type: roleInfo.type || 'custom',
status: 'active',
metadata: roleInfo.metadata || {},
createdAt: new Date(),
updatedAt: new Date()
};
this.roles.set(roleId, role);
// 记录审计日志
await this.auditLogger.log({
action: 'role:created',
details: { roleId, name: role.name },
timestamp: new Date()
});
// 发送事件
this.eventBus.emit('role:created', { role });
return role;
}
async updateRole(roleId: string, updates: UpdateRoleRequest): Promise<Role> {
const role = this.roles.get(roleId);
if (!role) {
throw new Error(`角色不存在: ${roleId}`);
}
const updatedRole: Role = {
...role,
...updates,
updatedAt: new Date()
};
this.roles.set(roleId, updatedRole);
// 记录审计日志
await this.auditLogger.log({
action: 'role:updated',
details: { roleId, updates },
timestamp: new Date()
});
// 发送事件
this.eventBus.emit('role:updated', { role: updatedRole, updates });
return updatedRole;
}
async deleteRole(roleId: string): Promise<void> {
const role = this.roles.get(roleId);
if (!role) {
throw new Error(`角色不存在: ${roleId}`);
}
// 检查是否有用户使用此角色
const usersWithRole = Array.from(this.userRoles.entries())
.filter(([_, roles]) => roles.has(roleId));
if (usersWithRole.length > 0) {
throw new Error(`无法删除角色,仍有 ${usersWithRole.length} 个用户使用此角色`);
}
// 删除角色权限关联
this.rolePermissions.delete(roleId);
// 删除角色
this.roles.delete(roleId);
// 记录审计日志
await this.auditLogger.log({
action: 'role:deleted',
details: { roleId, name: role.name },
timestamp: new Date()
});
// 发送事件
this.eventBus.emit('role:deleted', { roleId, role });
}
async getRole(roleId: string): Promise<Role | null> {
return this.roles.get(roleId) || null;
}
async queryRoles(query: RoleQuery): Promise<Role[]> {
let roles = Array.from(this.roles.values());
// 应用过滤条件
if (query.type) {
roles = roles.filter(role => role.type === query.type);
}
if (query.status) {
roles = roles.filter(role => role.status === query.status);
}
if (query.search) {
const searchLower = query.search.toLowerCase();
roles = roles.filter(role =>
role.name.toLowerCase().includes(searchLower) ||
role.description?.toLowerCase().includes(searchLower)
);
}
// 应用排序
if (query.sortBy) {
roles.sort((a, b) => {
const aValue = a[query.sortBy as keyof Role];
const bValue = b[query.sortBy as keyof Role];
const order = query.sortOrder === 'desc' ? -1 : 1;
if (aValue < bValue) return -1 * order;
if (aValue > bValue) return 1 * order;
return 0;
});
}
// 应用分页
const offset = ((query.page || 1) - 1) * (query.limit || 10);
const limit = query.limit || 10;
return roles.slice(offset, offset + limit);
}
// 权限管理实现
async createPermission(permissionInfo: CreatePermissionRequest): Promise<Permission> {
const permissionId = this.generateId();
const permission: Permission = {
id: permissionId,
name: permissionInfo.name,
description: permissionInfo.description,
resource: permissionInfo.resource,
action: permissionInfo.action,
conditions: permissionInfo.conditions || [],
metadata: permissionInfo.metadata || {},
createdAt: new Date(),
updatedAt: new Date()
};
this.permissions.set(permissionId, permission);
// 记录审计日志
await this.auditLogger.log({
action: 'permission:created',
details: { permissionId, name: permission.name, resource: permission.resource, action: permission.action },
timestamp: new Date()
});
// 发送事件
this.eventBus.emit('permission:created', { permission });
return permission;
}
async updatePermission(permissionId: string, updates: UpdatePermissionRequest): Promise<Permission> {
const permission = this.permissions.get(permissionId);
if (!permission) {
throw new Error(`权限不存在: ${permissionId}`);
}
const updatedPermission: Permission = {
...permission,
...updates,
updatedAt: new Date()
};
this.permissions.set(permissionId, updatedPermission);
// 记录审计日志
await this.auditLogger.log({
action: 'permission:updated',
details: { permissionId, updates },
timestamp: new Date()
});
// 发送事件
this.eventBus.emit('permission:updated', { permission: updatedPermission, updates });
return updatedPermission;
}
async deletePermission(permissionId: string): Promise<void> {
const permission = this.permissions.get(permissionId);
if (!permission) {
throw new Error(`权限不存在: ${permissionId}`);
}
// 检查是否有角色使用此权限
const rolesWithPermission = Array.from(this.rolePermissions.entries())
.filter(([_, permissions]) => permissions.has(permissionId));
if (rolesWithPermission.length > 0) {
throw new Error(`无法删除权限,仍有 ${rolesWithPermission.length} 个角色使用此权限`);
}
// 删除权限
this.permissions.delete(permissionId);
// 记录审计日志
await this.auditLogger.log({
action: 'permission:deleted',
details: { permissionId, name: permission.name },
timestamp: new Date()
});
// 发送事件
this.eventBus.emit('permission:deleted', { permissionId, permission });
}
async getPermission(permissionId: string): Promise<Permission | null> {
return this.permissions.get(permissionId) || null;
}
async queryPermissions(query: PermissionQuery): Promise<Permission[]> {
let permissions = Array.from(this.permissions.values());
// 应用过滤条件
if (query.resource) {
permissions = permissions.filter(permission => permission.resource === query.resource);
}
if (query.action) {
permissions = permissions.filter(permission => permission.action === query.action);
}
if (query.search) {
const searchLower = query.search.toLowerCase();
permissions = permissions.filter(permission =>
permission.name.toLowerCase().includes(searchLower) ||
permission.description?.toLowerCase().includes(searchLower)
);
}
// 应用排序
if (query.sortBy) {
permissions.sort((a, b) => {
const aValue = a[query.sortBy as keyof Permission];
const bValue = b[query.sortBy as keyof Permission];
const order = query.sortOrder === 'desc' ? -1 : 1;
if (aValue < bValue) return -1 * order;
if (aValue > bValue) return 1 * order;
return 0;
});
}
// 应用分页
const offset = ((query.page || 1) - 1) * (query.limit || 10);
const limit = query.limit || 10;
return permissions.slice(offset, offset + limit);
}
// 用户角色关联实现
async assignRoleToUser(userId: string, roleId: string): Promise<void> {
const user = this.users.get(userId);
const role = this.roles.get(roleId);
if (!user) {
throw new Error(`用户不存在: ${userId}`);
}
if (!role) {
throw new Error(`角色不存在: ${roleId}`);
}
if (!this.userRoles.has(userId)) {
this.userRoles.set(userId, new Set());
}
this.userRoles.get(userId)!.add(roleId);
// 记录审计日志
await this.auditLogger.log({
action: 'user:role:assigned',
userId: userId,
details: { roleId, roleName: role.name },
timestamp: new Date()
});
// 发送事件
this.eventBus.emit('user:role:assigned', { userId, roleId, user, role });
}
async removeRoleFromUser(userId: string, roleId: string): Promise<void> {
const user = this.users.get(userId);
const role = this.roles.get(roleId);
if (!user) {
throw new Error(`用户不存在: ${userId}`);
}
if (!role) {
throw new Error(`角色不存在: ${roleId}`);
}
const userRoleSet = this.userRoles.get(userId);
if (userRoleSet) {
userRoleSet.delete(roleId);
if (userRoleSet.size === 0) {
this.userRoles.delete(userId);
}
}
// 记录审计日志
await this.auditLogger.log({
action: 'user:role:removed',
userId: userId,
details: { roleId, roleName: role.name },
timestamp: new Date()
});
// 发送事件
this.eventBus.emit('user:role:removed', { userId, roleId, user, role });
}
async getUserRoles(userId: string): Promise<Role[]> {
const roleIds = this.userRoles.get(userId) || new Set();
const roles: Role[] = [];
for (const roleId of roleIds) {
const role = this.roles.get(roleId);
if (role) {
roles.push(role);
}
}
return roles;
}
// 角色权限关联实现
async assignPermissionToRole(roleId: string, permissionId: string): Promise<void> {
const role = this.roles.get(roleId);
const permission = this.permissions.get(permissionId);
if (!role) {
throw new Error(`角色不存在: ${roleId}`);
}
if (!permission) {
throw new Error(`权限不存在: ${permissionId}`);
}
if (!this.rolePermissions.has(roleId)) {
this.rolePermissions.set(roleId, new Set());
}
this.rolePermissions.get(roleId)!.add(permissionId);
// 记录审计日志
await this.auditLogger.log({
action: 'role:permission:assigned',
details: { roleId, roleName: role.name, permissionId, permissionName: permission.name },
timestamp: new Date()
});
// 发送事件
this.eventBus.emit('role:permission:assigned', { roleId, permissionId, role, permission });
}
async removePermissionFromRole(roleId: string, permissionId: string): Promise<void> {
const role = this.roles.get(roleId);
const permission = this.permissions.get(permissionId);
if (!role) {
throw new Error(`角色不存在: ${roleId}`);
}
if (!permission) {
throw new Error(`权限不存在: ${permissionId}`);
}
const rolePermissionSet = this.rolePermissions.get(roleId);
if (rolePermissionSet) {
rolePermissionSet.delete(permissionId);
if (rolePermissionSet.size === 0) {
this.rolePermissions.delete(roleId);
}
}
// 记录审计日志
await this.auditLogger.log({
action: 'role:permission:removed',
details: { roleId, roleName: role.name, permissionId, permissionName: permission.name },
timestamp: new Date()
});
// 发送事件
this.eventBus.emit('role:permission:removed', { roleId, permissionId, role, permission });
}
async getRolePermissions(roleId: string): Promise<Permission[]> {
const permissionIds = this.rolePermissions.get(roleId) || new Set();
const permissions: Permission[] = [];
for (const permissionId of permissionIds) {
const permission = this.permissions.get(permissionId);
if (permission) {
permissions.push(permission);
}
}
return permissions;
}
// 权限检查实现
async hasPermission(userId: string, resource: string, action: string): Promise<boolean> {
const userPermissions = await this.getUserPermissions(userId);
return userPermissions.some(permission =>
permission.resource === resource && permission.action === action
);
}
async checkPermission(userId: string, permissionCheck: PermissionCheck): Promise<boolean> {
const userPermissions = await this.getUserPermissions(userId);
for (const permission of userPermissions) {
if (permission.resource === permissionCheck.resource &&
permission.action === permissionCheck.action) {
// 检查条件
if (permission.conditions && permission.conditions.length > 0) {
const conditionsMet = await this.evaluateConditions(
permission.conditions,
permissionCheck.context || {}
);
if (conditionsMet) {
return true;
}
} else {
return true;
}
}
}
return false;
}
async getUserPermissions(userId: string): Promise<Permission[]> {
const userRoles = await this.getUserRoles(userId);
const permissions: Permission[] = [];
const permissionIds = new Set<string>();
for (const role of userRoles) {
const rolePermissions = await this.getRolePermissions(role.id);
for (const permission of rolePermissions) {
if (!permissionIds.has(permission.id)) {
permissions.push(permission);
permissionIds.add(permission.id);
}
}
}
return permissions;
}
// 资源管理实现
async registerResource(resource: ResourceDefinition): Promise<void> {
this.resources.set(resource.id, resource);
// 发送事件
this.eventBus.emit('resource:registered', { resource });
}
async unregisterResource(resourceId: string): Promise<void> {
const resource = this.resources.get(resourceId);
if (resource) {
this.resources.delete(resourceId);
// 发送事件
this.eventBus.emit('resource:unregistered', { resourceId, resource });
}
}
async getResource(resourceId: string): Promise<ResourceDefinition | null> {
return this.resources.get(resourceId) || null;
}
async listResources(): Promise<ResourceDefinition[]> {
return Array.from(this.resources.values());
}
// 私有方法
private generateId(): string {
return `${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
}
private async evaluateConditions(conditions: PermissionCondition[], context: Record<string, any>): Promise<boolean> {
for (const condition of conditions) {
const result = await this.evaluateCondition(condition, context);
if (!result) {
return false;
}
}
return true;
}
private async evaluateCondition(condition: PermissionCondition, context: Record<string, any>): Promise<boolean> {
const contextValue = context[condition.field];
const conditionValue = condition.value;
switch (condition.operator) {
case 'equals':
return contextValue === conditionValue;
case 'not_equals':
return contextValue !== conditionValue;
case 'in':
return Array.isArray(conditionValue) && conditionValue.includes(contextValue);
case 'not_in':
return Array.isArray(conditionValue) && !conditionValue.includes(contextValue);
case 'greater_than':
return contextValue > conditionValue;
case 'less_than':
return contextValue < conditionValue;
case 'contains':
return typeof contextValue === 'string' && contextValue.includes(conditionValue);
case 'starts_with':
return typeof contextValue === 'string' && contextValue.startsWith(conditionValue);
case 'ends_with':
return typeof contextValue === 'string' && contextValue.endsWith(conditionValue);
case 'regex':
return typeof contextValue === 'string' && new RegExp(conditionValue).test(contextValue);
default:
return false;
}
}
private initializeDefaultData(): void {
// 初始化默认资源
this.registerResource({
id: 'pages',
name: '页面管理',
description: '页面的创建、编辑、删除等操作',
actions: ['create', 'read', 'update', 'delete', 'publish']
});
this.registerResource({
id: 'components',
name: '组件管理',
description: '组件的创建、编辑、删除等操作',
actions: ['create', 'read', 'update', 'delete']
});
this.registerResource({
id: 'workflows',
name: '工作流管理',
description: '工作流的创建、编辑、删除等操作',
actions: ['create', 'read', 'update', 'delete', 'execute']
});
this.registerResource({
id: 'users',
name: '用户管理',
description: '用户的创建、编辑、删除等操作',
actions: ['create', 'read', 'update', 'delete']
});
this.registerResource({
id: 'roles',
name: '角色管理',
description: '角色的创建、编辑、删除等操作',
actions: ['create', 'read', 'update', 'delete']
});
this.registerResource({
id: 'permissions',
name: '权限管理',
description: '权限的创建、编辑、删除等操作',
actions: ['create', 'read', 'update', 'delete']
});
}
}
10.7 权限管理与安全控制使用示例
10.7.1 完整的权限管理系统示例
// 低代码权限管理与安全控制演示
class LowCodeSecurityDemo {
private permissionManager: PermissionManager;
private authManager: AuthenticationManager;
private securityMiddleware: SecurityMiddleware;
private dataMaskingService: DataMaskingService;
private encryptionService: EncryptionService;
private auditLogger: AuditLogger;
private eventBus: EventBus;
constructor() {
this.initializeServices();
this.setupEventListeners();
}
private initializeServices(): void {
// 初始化事件总线
this.eventBus = new EventBus();
// 初始化审计日志
this.auditLogger = new DefaultAuditLogger();
// 初始化加密服务
this.encryptionService = new DefaultEncryptionService({
secretKey: 'your-secret-key-here',
jwtSecret: 'your-jwt-secret-here'
});
// 初始化权限管理器
this.permissionManager = new LowCodePermissionManager({
encryptionService: this.encryptionService,
auditLogger: this.auditLogger,
eventBus: this.eventBus
});
// 初始化认证管理器
this.authManager = new LowCodeAuthenticationManager({
permissionManager: this.permissionManager,
encryptionService: this.encryptionService,
auditLogger: this.auditLogger,
eventBus: this.eventBus
});
// 初始化安全中间件
this.securityMiddleware = new LowCodeSecurityMiddleware({
authManager: this.authManager,
permissionManager: this.permissionManager,
rateLimiter: new MemoryRateLimiter(100, 60000),
inputValidator: new SimpleInputValidator(),
auditLogger: this.auditLogger
});
// 初始化数据脱敏服务
this.dataMaskingService = new DefaultDataMaskingService(this.encryptionService);
}
private setupEventListeners(): void {
// 监听用户登录事件
this.eventBus.on('auth:login', (data) => {
console.log(`用户 ${data.user.username} 登录成功`);
});
// 监听用户登出事件
this.eventBus.on('auth:logout', (data) => {
console.log(`用户会话 ${data.session.id} 已登出`);
});
// 监听权限变更事件
this.eventBus.on('permission:changed', (data) => {
console.log(`用户 ${data.userId} 的权限已更新`);
});
// 监听密码重置事件
this.eventBus.on('auth:password:reset:requested', (data) => {
console.log(`用户 ${data.user.email} 请求重置密码,令牌: ${data.resetToken}`);
// 这里通常会发送邮件
});
}
// 演示用户管理
async demonstrateUserManagement(): Promise<void> {
console.log('\n=== 用户管理演示 ===');
try {
// 创建管理员用户
const adminUser = await this.permissionManager.createUser({
username: 'admin',
email: 'admin@example.com',
password: 'admin123',
profile: {
firstName: '系统',
lastName: '管理员',
avatar: 'https://example.com/admin-avatar.jpg'
}
});
console.log('创建管理员用户:', adminUser.username);
// 创建普通用户
const normalUser = await this.permissionManager.createUser({
username: 'user1',
email: 'user1@example.com',
password: 'user123',
profile: {
firstName: '张',
lastName: '三',
avatar: 'https://example.com/user1-avatar.jpg'
}
});
console.log('创建普通用户:', normalUser.username);
// 查询用户
const users = await this.permissionManager.queryUsers({
search: 'user',
limit: 10,
offset: 0
});
console.log('查询到用户数量:', users.length);
// 更新用户信息
await this.permissionManager.updateUser(normalUser.id, {
profile: {
...normalUser.profile,
firstName: '李',
lastName: '四'
}
});
console.log('用户信息已更新');
} catch (error) {
console.error('用户管理演示失败:', error.message);
}
}
// 演示角色和权限管理
async demonstrateRolePermissionManagement(): Promise<void> {
console.log('\n=== 角色和权限管理演示 ===');
try {
// 创建权限
const readPermission = await this.permissionManager.createPermission({
name: 'read_users',
description: '查看用户信息',
resource: 'users',
action: 'read'
});
const writePermission = await this.permissionManager.createPermission({
name: 'write_users',
description: '编辑用户信息',
resource: 'users',
action: 'write'
});
const deletePermission = await this.permissionManager.createPermission({
name: 'delete_users',
description: '删除用户',
resource: 'users',
action: 'delete'
});
console.log('创建权限:', readPermission.name, writePermission.name, deletePermission.name);
// 创建角色
const adminRole = await this.permissionManager.createRole({
name: 'admin',
description: '系统管理员',
permissions: [readPermission.id, writePermission.id, deletePermission.id]
});
const userRole = await this.permissionManager.createRole({
name: 'user',
description: '普通用户',
permissions: [readPermission.id]
});
console.log('创建角色:', adminRole.name, userRole.name);
// 获取用户
const users = await this.permissionManager.queryUsers({ limit: 2 });
const adminUser = users.find(u => u.username === 'admin');
const normalUser = users.find(u => u.username === 'user1');
if (adminUser && normalUser) {
// 分配角色
await this.permissionManager.assignUserRole(adminUser.id, adminRole.id);
await this.permissionManager.assignUserRole(normalUser.id, userRole.id);
console.log('角色分配完成');
// 检查权限
const adminCanDelete = await this.permissionManager.checkPermission(
adminUser.id,
{ resource: 'users', action: 'delete' }
);
const userCanDelete = await this.permissionManager.checkPermission(
normalUser.id,
{ resource: 'users', action: 'delete' }
);
console.log('管理员删除权限:', adminCanDelete);
console.log('普通用户删除权限:', userCanDelete);
}
} catch (error) {
console.error('角色权限管理演示失败:', error.message);
}
}
// 演示认证流程
async demonstrateAuthentication(): Promise<void> {
console.log('\n=== 认证流程演示 ===');
try {
// 用户登录
const loginResult = await this.authManager.login({
username: 'admin',
password: 'admin123',
rememberMe: true
});
if (loginResult.success) {
console.log('登录成功:', loginResult.user?.username);
console.log('访问令牌:', loginResult.accessToken?.substring(0, 20) + '...');
// 验证令牌
const validationResult = await this.authManager.validateToken(loginResult.accessToken!);
console.log('令牌验证结果:', validationResult.valid);
// 刷新令牌
const refreshResult = await this.authManager.refreshToken(loginResult.refreshToken!);
if (refreshResult.success) {
console.log('令牌刷新成功');
}
// 修改密码
await this.authManager.changePassword(
loginResult.user!.id,
'admin123',
'newadmin123'
);
console.log('密码修改成功');
// 登出
await this.authManager.logout(loginResult.accessToken!);
console.log('用户已登出');
} else {
console.log('登录失败:', loginResult.error);
}
} catch (error) {
console.error('认证流程演示失败:', error.message);
}
}
// 演示安全中间件
async demonstrateSecurityMiddleware(): Promise<void> {
console.log('\n=== 安全中间件演示 ===');
try {
// 模拟请求
const request: SecurityRequest = {
headers: {
'authorization': 'Bearer invalid-token'
},
body: {
username: 'test',
email: 'test@example.com'
},
query: {
search: 'normal-query'
},
ip: '192.168.1.100',
userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
};
// 测试认证
const authResult = await this.securityMiddleware.authenticate(request);
console.log('认证结果:', authResult.success, authResult.error);
// 测试速率限制
const rateLimitResult = await this.securityMiddleware.rateLimit(request);
console.log('速率限制结果:', rateLimitResult.success);
// 测试输入验证
const validationResult = await this.securityMiddleware.validateInput(request);
console.log('输入验证结果:', validationResult.success);
// 测试恶意输入
const maliciousRequest: SecurityRequest = {
headers: {},
body: {
username: "'; DROP TABLE users; --",
script: '<script>alert("xss")</script>'
},
query: {
path: '../../../etc/passwd'
},
ip: '192.168.1.100'
};
const maliciousValidation = await this.securityMiddleware.validateInput(maliciousRequest);
console.log('恶意输入验证结果:', maliciousValidation.success, maliciousValidation.error);
} catch (error) {
console.error('安全中间件演示失败:', error.message);
}
}
// 演示数据脱敏
async demonstrateDataMasking(): Promise<void> {
console.log('\n=== 数据脱敏演示 ===');
try {
// 原始敏感数据
const sensitiveData = {
user: {
id: '12345',
username: 'john_doe',
email: 'john.doe@example.com',
phone: '13812345678',
idCard: '110101199001011234',
password: 'secret123',
bankCard: '6222021234567890123'
},
orders: [
{
id: 'order_001',
customerEmail: 'customer@example.com',
customerPhone: '13987654321',
amount: 299.99
}
]
};
console.log('原始数据:', JSON.stringify(sensitiveData, null, 2));
// 应用数据脱敏
const maskedData = this.dataMaskingService.maskSensitiveData(sensitiveData);
console.log('\n脱敏后数据:', JSON.stringify(maskedData, null, 2));
// 注册自定义脱敏规则
this.dataMaskingService.registerMaskingRule({
id: 'amount',
name: '金额脱敏',
fieldPattern: /amount|price|money/i,
maskingType: MaskingType.PARTIAL,
maskingOptions: {
keepStart: 1,
keepEnd: 2,
replacement: '*'
},
condition: (value) => typeof value === 'number' && value > 100
});
const customMaskedData = this.dataMaskingService.maskSensitiveData(sensitiveData);
console.log('\n自定义脱敏后数据:', JSON.stringify(customMaskedData, null, 2));
} catch (error) {
console.error('数据脱敏演示失败:', error.message);
}
}
// 演示审计日志
async demonstrateAuditLogging(): Promise<void> {
console.log('\n=== 审计日志演示 ===');
try {
// 记录各种操作的审计日志
await this.auditLogger.log({
action: 'user:create',
userId: 'user_123',
details: { username: 'new_user', email: 'new@example.com' },
timestamp: new Date()
});
await this.auditLogger.log({
action: 'permission:grant',
userId: 'admin_456',
details: { targetUserId: 'user_123', permission: 'read_users' },
timestamp: new Date()
});
await this.auditLogger.log({
action: 'data:access',
userId: 'user_123',
details: { resource: 'user_profiles', action: 'read', count: 10 },
timestamp: new Date()
});
// 查询审计日志
const logs = await this.auditLogger.queryLogs({
startTime: new Date(Date.now() - 24 * 60 * 60 * 1000), // 最近24小时
endTime: new Date(),
actions: ['user:create', 'permission:grant'],
limit: 10
});
console.log('查询到审计日志数量:', logs.length);
logs.forEach(log => {
console.log(`${log.timestamp.toISOString()} - ${log.action} - 用户: ${log.userId}`);
});
} catch (error) {
console.error('审计日志演示失败:', error.message);
}
}
// 运行完整演示
async runDemo(): Promise<void> {
console.log('开始低代码权限管理与安全控制演示...');
await this.demonstrateUserManagement();
await this.demonstrateRolePermissionManagement();
await this.demonstrateAuthentication();
await this.demonstrateSecurityMiddleware();
await this.demonstrateDataMasking();
await this.demonstrateAuditLogging();
console.log('\n演示完成!');
}
}
// 运行演示
const demo = new LowCodeSecurityDemo();
demo.runDemo().catch(console.error);
10.7.2 Web API 安全集成示例
// Express.js 中间件集成示例
import express from 'express';
class SecurityMiddlewareIntegration {
private securityMiddleware: SecurityMiddleware;
constructor(securityMiddleware: SecurityMiddleware) {
this.securityMiddleware = securityMiddleware;
}
// 认证中间件
authenticate() {
return async (req: express.Request, res: express.Response, next: express.NextFunction) => {
try {
const securityRequest: SecurityRequest = {
headers: req.headers as Record<string, string>,
body: req.body,
query: req.query as Record<string, string>,
params: req.params,
ip: req.ip,
userAgent: req.get('User-Agent')
};
const result = await this.securityMiddleware.authenticate(securityRequest);
if (!result.success) {
return res.status(result.statusCode || 401).json({
error: result.error
});
}
// 将用户信息附加到请求对象
(req as any).user = result.user;
(req as any).permissions = result.permissions;
next();
} catch (error) {
res.status(500).json({ error: '认证过程中发生错误' });
}
};
}
// 权限检查中间件
authorize(permission: PermissionCheck) {
return async (req: express.Request, res: express.Response, next: express.NextFunction) => {
try {
const securityRequest: SecurityRequest = {
headers: req.headers as Record<string, string>,
body: req.body,
query: req.query as Record<string, string>,
params: req.params,
ip: req.ip,
userAgent: req.get('User-Agent'),
user: (req as any).user
};
const result = await this.securityMiddleware.authorize(securityRequest, permission);
if (!result.success) {
return res.status(result.statusCode || 403).json({
error: result.error
});
}
next();
} catch (error) {
res.status(500).json({ error: '授权过程中发生错误' });
}
};
}
// 速率限制中间件
rateLimit() {
return async (req: express.Request, res: express.Response, next: express.NextFunction) => {
try {
const securityRequest: SecurityRequest = {
headers: req.headers as Record<string, string>,
ip: req.ip,
userAgent: req.get('User-Agent')
};
const result = await this.securityMiddleware.rateLimit(securityRequest);
if (!result.success) {
return res.status(result.statusCode || 429).json({
error: result.error
});
}
next();
} catch (error) {
res.status(500).json({ error: '速率限制检查失败' });
}
};
}
// 输入验证中间件
validateInput() {
return async (req: express.Request, res: express.Response, next: express.NextFunction) => {
try {
const securityRequest: SecurityRequest = {
headers: req.headers as Record<string, string>,
body: req.body,
query: req.query as Record<string, string>,
params: req.params,
ip: req.ip
};
const result = await this.securityMiddleware.validateInput(securityRequest);
if (!result.success) {
return res.status(result.statusCode || 400).json({
error: result.error
});
}
next();
} catch (error) {
res.status(500).json({ error: '输入验证失败' });
}
};
}
}
// 使用示例
const app = express();
const securityIntegration = new SecurityMiddlewareIntegration(securityMiddleware);
// 应用全局中间件
app.use(securityIntegration.rateLimit());
app.use(securityIntegration.validateInput());
// 需要认证的路由
app.use('/api/protected', securityIntegration.authenticate());
// 需要特定权限的路由
app.get('/api/users',
securityIntegration.authorize({ resource: 'users', action: 'read' }),
(req, res) => {
res.json({ message: '用户列表' });
}
);
app.post('/api/users',
securityIntegration.authorize({ resource: 'users', action: 'create' }),
(req, res) => {
res.json({ message: '用户创建成功' });
}
);
10.8 小结
本章详细介绍了低代码平台的权限管理与安全控制系统,涵盖了以下核心内容:
10.8.1 核心要点回顾
权限管理架构
- 用户、角色、权限的三层模型设计
- 基于资源和操作的权限控制机制
- 灵活的权限分配和检查系统
认证系统设计
- 完整的用户认证流程(登录、登出、令牌刷新)
- 会话管理和令牌验证机制
- 密码管理和重置功能
安全中间件
- 多层次的安全检查机制
- 速率限制和输入验证
- 统一的安全响应处理
数据安全保护
- 数据加密和解密服务
- 敏感数据脱敏处理
- 多种脱敏策略支持
审计和监控
- 完整的操作审计日志
- 安全事件记录和查询
- 实时安全监控能力
10.8.2 技术特色
- 类型安全:使用 TypeScript 提供完整的类型定义和检查
- 事件驱动:基于事件总线的松耦合架构设计
- 可扩展性:支持自定义权限规则和安全策略
- 高性能:优化的权限检查和缓存机制
- 安全性:多层次的安全防护和攻击检测
10.8.3 最佳实践
- 权限设计:遵循最小权限原则,合理设计权限粒度
- 密码安全:使用强密码策略和安全的哈希算法
- 令牌管理:合理设置令牌过期时间和刷新策略
- 审计日志:记录所有重要的安全操作和事件
- 数据保护:对敏感数据进行加密和脱敏处理
10.8.4 扩展方向
- 多因素认证:支持短信、邮箱、TOTP 等多种认证方式
- 单点登录:集成 SAML、OAuth2、OpenID Connect 等协议
- 行为分析:基于用户行为的异常检测和风险评估
- 合规支持:支持 GDPR、等保等合规要求
- 云原生安全:支持容器化部署和微服务架构
通过本章的学习,你已经掌握了构建安全可靠的低代码平台权限管理系统的核心技术。下一章我们将学习数据源管理与数据建模,探讨如何在低代码平台中管理和建模各种数据源。
10.3 核心数据结构
10.3.1 用户相关数据结构
// 用户状态枚举
enum UserStatus {
ACTIVE = 'active',
INACTIVE = 'inactive',
SUSPENDED = 'suspended',
DELETED = 'deleted'
}
// 用户接口
interface User {
id: string;
username: string;
email: string;
displayName?: string;
avatar?: string;
status: UserStatus;
passwordHash: string;
metadata: Record<string, any>;
createdAt: Date;
updatedAt: Date;
lastLoginAt: Date | null;
}
// 创建用户请求
interface CreateUserRequest {
username: string;
email: string;
password: string;
displayName?: string;
avatar?: string;
metadata?: Record<string, any>;
}
// 更新用户请求
interface UpdateUserRequest {
username?: string;
email?: string;
password?: string;
displayName?: string;
avatar?: string;
status?: UserStatus;
metadata?: Record<string, any>;
}
// 用户查询
interface UserQuery {
status?: UserStatus;
search?: string;
sortBy?: string;
sortOrder?: 'asc' | 'desc';
page?: number;
limit?: number;
}
10.3.2 角色相关数据结构
// 角色类型枚举
enum RoleType {
SYSTEM = 'system',
CUSTOM = 'custom'
}
// 角色状态枚举
enum RoleStatus {
ACTIVE = 'active',
INACTIVE = 'inactive'
}
// 角色接口
interface Role {
id: string;
name: string;
description?: string;
type: RoleType;
status: RoleStatus;
metadata: Record<string, any>;
createdAt: Date;
updatedAt: Date;
}
// 创建角色请求
interface CreateRoleRequest {
name: string;
description?: string;
type?: RoleType;
metadata?: Record<string, any>;
}
// 更新角色请求
interface UpdateRoleRequest {
name?: string;
description?: string;
status?: RoleStatus;
metadata?: Record<string, any>;
}
// 角色查询
interface RoleQuery {
type?: RoleType;
status?: RoleStatus;
search?: string;
sortBy?: string;
sortOrder?: 'asc' | 'desc';
page?: number;
limit?: number;
}
10.3.3 权限相关数据结构
// 权限条件操作符
type PermissionOperator =
| 'equals'
| 'not_equals'
| 'in'
| 'not_in'
| 'greater_than'
| 'less_than'
| 'contains'
| 'starts_with'
| 'ends_with'
| 'regex';
// 权限条件
interface PermissionCondition {
field: string;
operator: PermissionOperator;
value: any;
}
// 权限接口
interface Permission {
id: string;
name: string;
description?: string;
resource: string;
action: string;
conditions?: PermissionCondition[];
metadata: Record<string, any>;
createdAt: Date;
updatedAt: Date;
}
// 创建权限请求
interface CreatePermissionRequest {
name: string;
description?: string;
resource: string;
action: string;
conditions?: PermissionCondition[];
metadata?: Record<string, any>;
}
// 更新权限请求
interface UpdatePermissionRequest {
name?: string;
description?: string;
resource?: string;
action?: string;
conditions?: PermissionCondition[];
metadata?: Record<string, any>;
}
// 权限查询
interface PermissionQuery {
resource?: string;
action?: string;
search?: string;
sortBy?: string;
sortOrder?: 'asc' | 'desc';
page?: number;
limit?: number;
}
// 权限检查
interface PermissionCheck {
resource: string;
action: string;
context?: Record<string, any>;
}
// 资源定义
interface ResourceDefinition {
id: string;
name: string;
description?: string;
actions: string[];
}
10.3.4 配置和选项
// 权限管理器选项
interface PermissionManagerOptions {
eventBus: EventBus;
auditLogger: AuditLogger;
encryptionService: EncryptionService;
}
// 审计日志接口
interface AuditLogger {
log(entry: AuditLogEntry): Promise<void>;
query(query: AuditLogQuery): Promise<AuditLogEntry[]>;
}
// 审计日志条目
interface AuditLogEntry {
id?: string;
action: string;
userId?: string;
details: Record<string, any>;
timestamp: Date;
ip?: string;
userAgent?: string;
}
// 审计日志查询
interface AuditLogQuery {
action?: string;
userId?: string;
startDate?: Date;
endDate?: Date;
page?: number;
limit?: number;
}
// 加密服务接口
interface EncryptionService {
hashPassword(password: string): Promise<string>;
verifyPassword(password: string, hash: string): Promise<boolean>;
encrypt(data: string): Promise<string>;
decrypt(encryptedData: string): Promise<string>;
generateToken(payload: Record<string, any>): Promise<string>;
verifyToken(token: string): Promise<Record<string, any> | null>;
}
10.4 认证系统
10.4.1 认证管理器
// 认证管理器接口
interface AuthenticationManager {
login(credentials: LoginCredentials): Promise<AuthenticationResult>;
logout(token: string): Promise<void>;
refreshToken(refreshToken: string): Promise<AuthenticationResult>;
validateToken(token: string): Promise<TokenValidationResult>;
changePassword(userId: string, oldPassword: string, newPassword: string): Promise<void>;
resetPassword(email: string): Promise<void>;
confirmPasswordReset(token: string, newPassword: string): Promise<void>;
}
// 登录凭据
interface LoginCredentials {
username: string;
password: string;
rememberMe?: boolean;
}
// 认证结果
interface AuthenticationResult {
success: boolean;
user?: User;
accessToken?: string;
refreshToken?: string;
expiresIn?: number;
error?: string;
}
// 令牌验证结果
interface TokenValidationResult {
valid: boolean;
user?: User;
permissions?: Permission[];
error?: string;
}
// 低代码认证管理器实现
class LowCodeAuthenticationManager implements AuthenticationManager {
private permissionManager: PermissionManager;
private encryptionService: EncryptionService;
private auditLogger: AuditLogger;
private eventBus: EventBus;
private activeSessions: Map<string, AuthSession> = new Map();
private passwordResetTokens: Map<string, PasswordResetToken> = new Map();
constructor(options: AuthenticationManagerOptions) {
this.permissionManager = options.permissionManager;
this.encryptionService = options.encryptionService;
this.auditLogger = options.auditLogger;
this.eventBus = options.eventBus;
}
async login(credentials: LoginCredentials): Promise<AuthenticationResult> {
try {
// 查找用户
const users = await this.permissionManager.queryUsers({
search: credentials.username,
limit: 1
});
const user = users.find(u =>
u.username === credentials.username || u.email === credentials.username
);
if (!user) {
await this.auditLogger.log({
action: 'auth:login:failed',
details: { username: credentials.username, reason: 'user_not_found' },
timestamp: new Date()
});
return {
success: false,
error: '用户名或密码错误'
};
}
// 检查用户状态
if (user.status !== 'active') {
await this.auditLogger.log({
action: 'auth:login:failed',
userId: user.id,
details: { username: credentials.username, reason: 'user_inactive', status: user.status },
timestamp: new Date()
});
return {
success: false,
error: '账户已被禁用'
};
}
// 验证密码
const passwordValid = await this.encryptionService.verifyPassword(
credentials.password,
user.passwordHash
);
if (!passwordValid) {
await this.auditLogger.log({
action: 'auth:login:failed',
userId: user.id,
details: { username: credentials.username, reason: 'invalid_password' },
timestamp: new Date()
});
return {
success: false,
error: '用户名或密码错误'
};
}
// 生成令牌
const tokenPayload = {
userId: user.id,
username: user.username,
email: user.email,
iat: Date.now()
};
const accessToken = await this.encryptionService.generateToken(tokenPayload);
const refreshToken = await this.encryptionService.generateToken({
...tokenPayload,
type: 'refresh'
});
// 创建会话
const session: AuthSession = {
id: this.generateSessionId(),
userId: user.id,
accessToken,
refreshToken,
createdAt: new Date(),
expiresAt: new Date(Date.now() + (credentials.rememberMe ? 30 * 24 * 60 * 60 * 1000 : 24 * 60 * 60 * 1000)),
lastAccessAt: new Date(),
metadata: {
rememberMe: credentials.rememberMe || false
}
};
this.activeSessions.set(session.id, session);
// 更新用户最后登录时间
await this.permissionManager.updateUser(user.id, {
lastLoginAt: new Date()
});
// 记录审计日志
await this.auditLogger.log({
action: 'auth:login:success',
userId: user.id,
details: { username: credentials.username, sessionId: session.id },
timestamp: new Date()
});
// 发送事件
this.eventBus.emit('auth:login', { user, session });
return {
success: true,
user,
accessToken,
refreshToken,
expiresIn: Math.floor((session.expiresAt.getTime() - Date.now()) / 1000)
};
} catch (error) {
await this.auditLogger.log({
action: 'auth:login:error',
details: { username: credentials.username, error: error.message },
timestamp: new Date()
});
return {
success: false,
error: '登录过程中发生错误'
};
}
}
async logout(token: string): Promise<void> {
try {
const session = this.findSessionByToken(token);
if (session) {
this.activeSessions.delete(session.id);
// 记录审计日志
await this.auditLogger.log({
action: 'auth:logout',
userId: session.userId,
details: { sessionId: session.id },
timestamp: new Date()
});
// 发送事件
this.eventBus.emit('auth:logout', { session });
}
} catch (error) {
console.error('Logout error:', error);
}
}
async refreshToken(refreshToken: string): Promise<AuthenticationResult> {
try {
// 验证刷新令牌
const tokenData = await this.encryptionService.verifyToken(refreshToken);
if (!tokenData || tokenData.type !== 'refresh') {
return {
success: false,
error: '无效的刷新令牌'
};
}
// 查找会话
const session = Array.from(this.activeSessions.values())
.find(s => s.refreshToken === refreshToken);
if (!session || session.expiresAt < new Date()) {
return {
success: false,
error: '会话已过期'
};
}
// 获取用户信息
const user = await this.permissionManager.getUser(session.userId);
if (!user || user.status !== 'active') {
return {
success: false,
error: '用户不存在或已被禁用'
};
}
// 生成新的访问令牌
const newTokenPayload = {
userId: user.id,
username: user.username,
email: user.email,
iat: Date.now()
};
const newAccessToken = await this.encryptionService.generateToken(newTokenPayload);
// 更新会话
session.accessToken = newAccessToken;
session.lastAccessAt = new Date();
// 记录审计日志
await this.auditLogger.log({
action: 'auth:token:refreshed',
userId: user.id,
details: { sessionId: session.id },
timestamp: new Date()
});
return {
success: true,
user,
accessToken: newAccessToken,
refreshToken,
expiresIn: Math.floor((session.expiresAt.getTime() - Date.now()) / 1000)
};
} catch (error) {
return {
success: false,
error: '令牌刷新失败'
};
}
}
async validateToken(token: string): Promise<TokenValidationResult> {
try {
// 验证令牌
const tokenData = await this.encryptionService.verifyToken(token);
if (!tokenData) {
return {
valid: false,
error: '无效的令牌'
};
}
// 查找会话
const session = this.findSessionByToken(token);
if (!session || session.expiresAt < new Date()) {
return {
valid: false,
error: '会话已过期'
};
}
// 获取用户信息
const user = await this.permissionManager.getUser(session.userId);
if (!user || user.status !== 'active') {
return {
valid: false,
error: '用户不存在或已被禁用'
};
}
// 获取用户权限
const permissions = await this.permissionManager.getUserPermissions(user.id);
// 更新最后访问时间
session.lastAccessAt = new Date();
return {
valid: true,
user,
permissions
};
} catch (error) {
return {
valid: false,
error: '令牌验证失败'
};
}
}
async changePassword(userId: string, oldPassword: string, newPassword: string): Promise<void> {
const user = await this.permissionManager.getUser(userId);
if (!user) {
throw new Error('用户不存在');
}
// 验证旧密码
const oldPasswordValid = await this.encryptionService.verifyPassword(
oldPassword,
user.passwordHash
);
if (!oldPasswordValid) {
throw new Error('原密码错误');
}
// 更新密码
await this.permissionManager.updateUser(userId, {
password: newPassword
});
// 记录审计日志
await this.auditLogger.log({
action: 'auth:password:changed',
userId: userId,
details: {},
timestamp: new Date()
});
// 发送事件
this.eventBus.emit('auth:password:changed', { userId, user });
}
async resetPassword(email: string): Promise<void> {
const users = await this.permissionManager.queryUsers({
search: email,
limit: 1
});
const user = users.find(u => u.email === email);
if (!user) {
// 为了安全,即使用户不存在也不抛出错误
return;
}
// 生成重置令牌
const resetToken = this.generateResetToken();
const resetTokenData: PasswordResetToken = {
token: resetToken,
userId: user.id,
email: user.email,
expiresAt: new Date(Date.now() + 60 * 60 * 1000), // 1小时后过期
createdAt: new Date()
};
this.passwordResetTokens.set(resetToken, resetTokenData);
// 记录审计日志
await this.auditLogger.log({
action: 'auth:password:reset:requested',
userId: user.id,
details: { email },
timestamp: new Date()
});
// 发送事件(通常会触发邮件发送)
this.eventBus.emit('auth:password:reset:requested', { user, resetToken });
}
async confirmPasswordReset(token: string, newPassword: string): Promise<void> {
const resetTokenData = this.passwordResetTokens.get(token);
if (!resetTokenData || resetTokenData.expiresAt < new Date()) {
throw new Error('重置令牌无效或已过期');
}
// 更新密码
await this.permissionManager.updateUser(resetTokenData.userId, {
password: newPassword
});
// 删除重置令牌
this.passwordResetTokens.delete(token);
// 记录审计日志
await this.auditLogger.log({
action: 'auth:password:reset:confirmed',
userId: resetTokenData.userId,
details: {},
timestamp: new Date()
});
// 发送事件
this.eventBus.emit('auth:password:reset:confirmed', { userId: resetTokenData.userId });
}
// 私有方法
private generateSessionId(): string {
return `session_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
}
private generateResetToken(): string {
return `reset_${Date.now()}_${Math.random().toString(36).substr(2, 16)}`;
}
private findSessionByToken(token: string): AuthSession | null {
return Array.from(this.activeSessions.values())
.find(session => session.accessToken === token) || null;
}
}
// 认证会话
interface AuthSession {
id: string;
userId: string;
accessToken: string;
refreshToken: string;
createdAt: Date;
expiresAt: Date;
lastAccessAt: Date;
metadata: Record<string, any>;
}
// 密码重置令牌
interface PasswordResetToken {
token: string;
userId: string;
email: string;
expiresAt: Date;
createdAt: Date;
}
// 认证管理器选项
interface AuthenticationManagerOptions {
permissionManager: PermissionManager;
encryptionService: EncryptionService;
auditLogger: AuditLogger;
eventBus: EventBus;
}
10.5 安全中间件
10.5.1 权限检查中间件
// 安全中间件接口
interface SecurityMiddleware {
authenticate(request: SecurityRequest): Promise<SecurityResponse>;
authorize(request: SecurityRequest, permission: PermissionCheck): Promise<SecurityResponse>;
rateLimit(request: SecurityRequest): Promise<SecurityResponse>;
validateInput(request: SecurityRequest): Promise<SecurityResponse>;
}
// 安全请求
interface SecurityRequest {
headers: Record<string, string>;
body?: any;
query?: Record<string, string>;
params?: Record<string, string>;
ip?: string;
userAgent?: string;
user?: User;
}
// 安全响应
interface SecurityResponse {
success: boolean;
user?: User;
permissions?: Permission[];
error?: string;
statusCode?: number;
}
// 低代码安全中间件实现
class LowCodeSecurityMiddleware implements SecurityMiddleware {
private authManager: AuthenticationManager;
private permissionManager: PermissionManager;
private rateLimiter: RateLimiter;
private inputValidator: InputValidator;
private auditLogger: AuditLogger;
constructor(options: SecurityMiddlewareOptions) {
this.authManager = options.authManager;
this.permissionManager = options.permissionManager;
this.rateLimiter = options.rateLimiter;
this.inputValidator = options.inputValidator;
this.auditLogger = options.auditLogger;
}
async authenticate(request: SecurityRequest): Promise<SecurityResponse> {
try {
// 提取令牌
const token = this.extractToken(request);
if (!token) {
return {
success: false,
error: '缺少认证令牌',
statusCode: 401
};
}
// 验证令牌
const validationResult = await this.authManager.validateToken(token);
if (!validationResult.valid) {
return {
success: false,
error: validationResult.error || '认证失败',
statusCode: 401
};
}
return {
success: true,
user: validationResult.user,
permissions: validationResult.permissions
};
} catch (error) {
await this.auditLogger.log({
action: 'security:auth:error',
details: { error: error.message, ip: request.ip },
timestamp: new Date()
});
return {
success: false,
error: '认证过程中发生错误',
statusCode: 500
};
}
}
async authorize(request: SecurityRequest, permission: PermissionCheck): Promise<SecurityResponse> {
try {
// 首先进行认证
const authResult = await this.authenticate(request);
if (!authResult.success || !authResult.user) {
return authResult;
}
// 检查权限
const hasPermission = await this.permissionManager.checkPermission(
authResult.user.id,
permission
);
if (!hasPermission) {
await this.auditLogger.log({
action: 'security:auth:unauthorized',
userId: authResult.user.id,
details: {
resource: permission.resource,
action: permission.action,
ip: request.ip
},
timestamp: new Date()
});
return {
success: false,
error: '权限不足',
statusCode: 403
};
}
return {
success: true,
user: authResult.user,
permissions: authResult.permissions
};
} catch (error) {
await this.auditLogger.log({
action: 'security:auth:error',
details: { error: error.message, ip: request.ip },
timestamp: new Date()
});
return {
success: false,
error: '授权过程中发生错误',
statusCode: 500
};
}
}
async rateLimit(request: SecurityRequest): Promise<SecurityResponse> {
try {
const identifier = request.ip || 'unknown';
const allowed = await this.rateLimiter.isAllowed(identifier);
if (!allowed) {
await this.auditLogger.log({
action: 'security:rate_limit:exceeded',
details: { ip: request.ip, userAgent: request.userAgent },
timestamp: new Date()
});
return {
success: false,
error: '请求频率过高,请稍后再试',
statusCode: 429
};
}
return {
success: true
};
} catch (error) {
return {
success: false,
error: '速率限制检查失败',
statusCode: 500
};
}
}
async validateInput(request: SecurityRequest): Promise<SecurityResponse> {
try {
const validationResult = await this.inputValidator.validate(request);
if (!validationResult.valid) {
await this.auditLogger.log({
action: 'security:input:invalid',
details: {
errors: validationResult.errors,
ip: request.ip
},
timestamp: new Date()
});
return {
success: false,
error: `输入验证失败: ${validationResult.errors.join(', ')}`,
statusCode: 400
};
}
return {
success: true
};
} catch (error) {
return {
success: false,
error: '输入验证过程中发生错误',
statusCode: 500
};
}
}
private extractToken(request: SecurityRequest): string | null {
const authHeader = request.headers['authorization'] || request.headers['Authorization'];
if (authHeader && authHeader.startsWith('Bearer ')) {
return authHeader.substring(7);
}
// 也可以从查询参数中获取
return request.query?.token || null;
}
}
// 速率限制器接口
interface RateLimiter {
isAllowed(identifier: string): Promise<boolean>;
getRemainingRequests(identifier: string): Promise<number>;
reset(identifier: string): Promise<void>;
}
// 简单的内存速率限制器
class MemoryRateLimiter implements RateLimiter {
private requests: Map<string, RequestRecord> = new Map();
private maxRequests: number;
private windowMs: number;
constructor(maxRequests: number = 100, windowMs: number = 60000) {
this.maxRequests = maxRequests;
this.windowMs = windowMs;
// 定期清理过期记录
setInterval(() => this.cleanup(), this.windowMs);
}
async isAllowed(identifier: string): Promise<boolean> {
const now = Date.now();
const record = this.requests.get(identifier);
if (!record || now - record.windowStart > this.windowMs) {
// 新窗口或第一次请求
this.requests.set(identifier, {
count: 1,
windowStart: now
});
return true;
}
if (record.count >= this.maxRequests) {
return false;
}
record.count++;
return true;
}
async getRemainingRequests(identifier: string): Promise<number> {
const record = this.requests.get(identifier);
if (!record) {
return this.maxRequests;
}
return Math.max(0, this.maxRequests - record.count);
}
async reset(identifier: string): Promise<void> {
this.requests.delete(identifier);
}
private cleanup(): void {
const now = Date.now();
for (const [identifier, record] of this.requests.entries()) {
if (now - record.windowStart > this.windowMs) {
this.requests.delete(identifier);
}
}
}
}
// 请求记录
interface RequestRecord {
count: number;
windowStart: number;
}
// 输入验证器接口
interface InputValidator {
validate(request: SecurityRequest): Promise<ValidationResult>;
}
// 验证结果
interface ValidationResult {
valid: boolean;
errors: string[];
}
// 简单的输入验证器
class SimpleInputValidator implements InputValidator {
async validate(request: SecurityRequest): Promise<ValidationResult> {
const errors: string[] = [];
// 检查SQL注入
if (this.containsSqlInjection(request)) {
errors.push('检测到潜在的SQL注入攻击');
}
// 检查XSS
if (this.containsXss(request)) {
errors.push('检测到潜在的XSS攻击');
}
// 检查路径遍历
if (this.containsPathTraversal(request)) {
errors.push('检测到潜在的路径遍历攻击');
}
return {
valid: errors.length === 0,
errors
};
}
private containsSqlInjection(request: SecurityRequest): boolean {
const sqlPatterns = [
/('|(\-\-)|(;)|(\||\|)|(\*|\*))/i,
/(union|select|insert|delete|update|drop|create|alter|exec|execute)/i
];
return this.checkPatterns(request, sqlPatterns);
}
private containsXss(request: SecurityRequest): boolean {
const xssPatterns = [
/<script[^>]*>.*?<\/script>/gi,
/<iframe[^>]*>.*?<\/iframe>/gi,
/javascript:/gi,
/on\w+\s*=/gi
];
return this.checkPatterns(request, xssPatterns);
}
private containsPathTraversal(request: SecurityRequest): boolean {
const pathPatterns = [
/\.\.[\/\\]/,
/\.\.%2f/i,
/\.\.%5c/i
];
return this.checkPatterns(request, pathPatterns);
}
private checkPatterns(request: SecurityRequest, patterns: RegExp[]): boolean {
const values = [
...Object.values(request.query || {}),
...Object.values(request.params || {}),
JSON.stringify(request.body || {})
];
for (const value of values) {
const stringValue = String(value);
for (const pattern of patterns) {
if (pattern.test(stringValue)) {
return true;
}
}
}
return false;
}
}
// 安全中间件选项
interface SecurityMiddlewareOptions {
authManager: AuthenticationManager;
permissionManager: PermissionManager;
rateLimiter: RateLimiter;
inputValidator: InputValidator;
auditLogger: AuditLogger;
}
10.6 数据安全
10.6.1 数据加密服务
// 数据加密服务实现
class DefaultEncryptionService implements EncryptionService {
private secretKey: string;
private algorithm: string = 'aes-256-gcm';
private jwtSecret: string;
constructor(options: EncryptionServiceOptions) {
this.secretKey = options.secretKey;
this.jwtSecret = options.jwtSecret;
}
async hashPassword(password: string): Promise<string> {
const bcrypt = require('bcrypt');
const saltRounds = 12;
return await bcrypt.hash(password, saltRounds);
}
async verifyPassword(password: string, hash: string): Promise<boolean> {
const bcrypt = require('bcrypt');
return await bcrypt.compare(password, hash);
}
async encrypt(data: string): Promise<string> {
const crypto = require('crypto');
const iv = crypto.randomBytes(16);
const cipher = crypto.createCipher(this.algorithm, this.secretKey);
cipher.setAAD(Buffer.from('lowcode-platform'));
let encrypted = cipher.update(data, 'utf8', 'hex');
encrypted += cipher.final('hex');
const authTag = cipher.getAuthTag();
return `${iv.toString('hex')}:${authTag.toString('hex')}:${encrypted}`;
}
async decrypt(encryptedData: string): Promise<string> {
const crypto = require('crypto');
const [ivHex, authTagHex, encrypted] = encryptedData.split(':');
const iv = Buffer.from(ivHex, 'hex');
const authTag = Buffer.from(authTagHex, 'hex');
const decipher = crypto.createDecipher(this.algorithm, this.secretKey);
decipher.setAAD(Buffer.from('lowcode-platform'));
decipher.setAuthTag(authTag);
let decrypted = decipher.update(encrypted, 'hex', 'utf8');
decrypted += decipher.final('utf8');
return decrypted;
}
async generateToken(payload: Record<string, any>): Promise<string> {
const jwt = require('jsonwebtoken');
return jwt.sign(payload, this.jwtSecret, {
expiresIn: '24h',
issuer: 'lowcode-platform',
audience: 'lowcode-users'
});
}
async verifyToken(token: string): Promise<Record<string, any> | null> {
try {
const jwt = require('jsonwebtoken');
return jwt.verify(token, this.jwtSecret, {
issuer: 'lowcode-platform',
audience: 'lowcode-users'
});
} catch (error) {
return null;
}
}
}
// 加密服务选项
interface EncryptionServiceOptions {
secretKey: string;
jwtSecret: string;
}
10.6.2 数据脱敏服务
// 数据脱敏服务接口
interface DataMaskingService {
maskSensitiveData(data: any, rules: MaskingRule[]): any;
unmaskSensitiveData(data: any, rules: MaskingRule[]): any;
registerMaskingRule(rule: MaskingRule): void;
getMaskingRules(): MaskingRule[];
}
// 脱敏规则
interface MaskingRule {
id: string;
name: string;
fieldPattern: string | RegExp;
maskingType: MaskingType;
maskingOptions?: MaskingOptions;
condition?: (value: any, context: any) => boolean;
}
// 脱敏类型
enum MaskingType {
REPLACE = 'replace',
PARTIAL = 'partial',
HASH = 'hash',
ENCRYPT = 'encrypt',
REMOVE = 'remove'
}
// 脱敏选项
interface MaskingOptions {
replacement?: string;
keepStart?: number;
keepEnd?: number;
hashAlgorithm?: string;
encryptionKey?: string;
}
// 数据脱敏服务实现
class DefaultDataMaskingService implements DataMaskingService {
private rules: Map<string, MaskingRule> = new Map();
private encryptionService: EncryptionService;
constructor(encryptionService: EncryptionService) {
this.encryptionService = encryptionService;
this.initializeDefaultRules();
}
maskSensitiveData(data: any, rules: MaskingRule[] = []): any {
const allRules = [...Array.from(this.rules.values()), ...rules];
return this.processData(data, allRules, true);
}
unmaskSensitiveData(data: any, rules: MaskingRule[] = []): any {
const allRules = [...Array.from(this.rules.values()), ...rules];
return this.processData(data, allRules, false);
}
registerMaskingRule(rule: MaskingRule): void {
this.rules.set(rule.id, rule);
}
getMaskingRules(): MaskingRule[] {
return Array.from(this.rules.values());
}
private processData(data: any, rules: MaskingRule[], mask: boolean): any {
if (data === null || data === undefined) {
return data;
}
if (Array.isArray(data)) {
return data.map(item => this.processData(item, rules, mask));
}
if (typeof data === 'object') {
const result: any = {};
for (const [key, value] of Object.entries(data)) {
const applicableRule = this.findApplicableRule(key, value, rules);
if (applicableRule) {
result[key] = mask
? this.applyMasking(value, applicableRule)
: this.applyUnmasking(value, applicableRule);
} else {
result[key] = this.processData(value, rules, mask);
}
}
return result;
}
return data;
}
private findApplicableRule(fieldName: string, value: any, rules: MaskingRule[]): MaskingRule | null {
for (const rule of rules) {
const pattern = rule.fieldPattern;
let matches = false;
if (typeof pattern === 'string') {
matches = fieldName === pattern;
} else if (pattern instanceof RegExp) {
matches = pattern.test(fieldName);
}
if (matches && (!rule.condition || rule.condition(value, { fieldName }))) {
return rule;
}
}
return null;
}
private applyMasking(value: any, rule: MaskingRule): any {
if (value === null || value === undefined) {
return value;
}
const stringValue = String(value);
switch (rule.maskingType) {
case MaskingType.REPLACE:
return rule.maskingOptions?.replacement || '***';
case MaskingType.PARTIAL:
return this.applyPartialMasking(stringValue, rule.maskingOptions);
case MaskingType.HASH:
return this.applyHashMasking(stringValue, rule.maskingOptions);
case MaskingType.ENCRYPT:
return this.applyEncryptionMasking(stringValue);
case MaskingType.REMOVE:
return undefined;
default:
return value;
}
}
private applyUnmasking(value: any, rule: MaskingRule): any {
if (value === null || value === undefined) {
return value;
}
switch (rule.maskingType) {
case MaskingType.ENCRYPT:
try {
return this.encryptionService.decrypt(String(value));
} catch {
return value; // 如果解密失败,返回原值
}
default:
return value; // 其他类型的脱敏无法逆转
}
}
private applyPartialMasking(value: string, options?: MaskingOptions): string {
const keepStart = options?.keepStart || 2;
const keepEnd = options?.keepEnd || 2;
const replacement = options?.replacement || '*';
if (value.length <= keepStart + keepEnd) {
return replacement.repeat(value.length);
}
const start = value.substring(0, keepStart);
const end = value.substring(value.length - keepEnd);
const middle = replacement.repeat(value.length - keepStart - keepEnd);
return start + middle + end;
}
private applyHashMasking(value: string, options?: MaskingOptions): string {
const crypto = require('crypto');
const algorithm = options?.hashAlgorithm || 'sha256';
return crypto.createHash(algorithm).update(value).digest('hex');
}
private async applyEncryptionMasking(value: string): Promise<string> {
return await this.encryptionService.encrypt(value);
}
private initializeDefaultRules(): void {
// 邮箱脱敏
this.registerMaskingRule({
id: 'email',
name: '邮箱脱敏',
fieldPattern: /email|mail/i,
maskingType: MaskingType.PARTIAL,
maskingOptions: {
keepStart: 2,
keepEnd: 0,
replacement: '*'
},
condition: (value) => typeof value === 'string' && value.includes('@')
});
// 手机号脱敏
this.registerMaskingRule({
id: 'phone',
name: '手机号脱敏',
fieldPattern: /phone|mobile|tel/i,
maskingType: MaskingType.PARTIAL,
maskingOptions: {
keepStart: 3,
keepEnd: 4,
replacement: '*'
},
condition: (value) => typeof value === 'string' && /^\d{11}$/.test(value)
});
// 身份证号脱敏
this.registerMaskingRule({
id: 'idcard',
name: '身份证号脱敏',
fieldPattern: /id|idcard|identity/i,
maskingType: MaskingType.PARTIAL,
maskingOptions: {
keepStart: 4,
keepEnd: 4,
replacement: '*'
},
condition: (value) => typeof value === 'string' && /^\d{15}|\d{18}$/.test(value)
});
// 密码脱敏
this.registerMaskingRule({
id: 'password',
name: '密码脱敏',
fieldPattern: /password|pwd|pass/i,
maskingType: MaskingType.REPLACE,
maskingOptions: {
replacement: '******'
}
});
// 银行卡号脱敏
this.registerMaskingRule({
id: 'bankcard',
name: '银行卡号脱敏',
fieldPattern: /card|bank/i,
maskingType: MaskingType.PARTIAL,
maskingOptions: {
keepStart: 4,
keepEnd: 4,
replacement: '*'
},
condition: (value) => typeof value === 'string' && /^\d{16,19}$/.test(value)
});
}
}