📖 数据密集型设计

RBAC权限模型与访问控制

深入探讨RBAC权限模型与访问控制实现

一、RBAC概述

RBAC(Role-Based Access Control)是基于角色的访问控制模型,通过角色来管理用户对资源的访问权限。RBAC是企业级应用中最常用的权限管理方案。

二、RBAC模型

2.1 RBAC基本模型

RBAC包含四个核心元素:用户、角色、权限和资源:

erDiagram USER ||--o{ ROLE : "拥有" ROLE ||--o{ PERMISSION : "授予" PERMISSION ||--o{ RESOURCE : "访问" USER { int user_id PK string username string email } ROLE { int role_id PK string role_name string description } PERMISSION { int permission_id PK string permission_name string action string resource }

2.2 RBAC层级

graph TD A[用户层] --> B[角色层] B --> C[权限层] C --> D[资源层] A --> A1[普通用户] A --> A2[管理员] A --> A3[超级管理员] B --> B1[用户角色] B --> B2[编辑角色] B --> B3[审核角色] C --> C1[查看权限] C --> C2[编辑权限] C --> C3[删除权限] D --> D1[文章资源] D --> D2[用户资源] D --> D3[配置资源]

三、RBAC实现

3.1 数据库设计

-- 用户表
CREATE TABLE users (
    id INT PRIMARY KEY AUTO_INCREMENT,
    username VARCHAR(50) NOT NULL,
    email VARCHAR(100) NOT NULL,
    password VARCHAR(255) NOT NULL,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

-- 角色表
CREATE TABLE roles (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(50) NOT NULL UNIQUE,
    description VARCHAR(255),
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

-- 用户角色关联表
CREATE TABLE user_roles (
    user_id INT,
    role_id INT,
    PRIMARY KEY (user_id, role_id),
    FOREIGN KEY (user_id) REFERENCES users(id),
    FOREIGN KEY (role_id) REFERENCES roles(id)
);

-- 权限表
CREATE TABLE permissions (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(50) NOT NULL,
    action VARCHAR(50) NOT NULL,
    resource VARCHAR(50) NOT NULL,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

-- 角色权限关联表
CREATE TABLE role_permissions (
    role_id INT,
    permission_id INT,
    PRIMARY KEY (role_id, permission_id),
    FOREIGN KEY (role_id) REFERENCES roles(id),
    FOREIGN KEY (permission_id) REFERENCES permissions(id)
);

3.2 权限检查实现

public class PermissionService
{
    private readonly DbContext _db;
    
    public bool HasPermission(int userId, string action, string resource)
    {
        return _db.UserRoles
            .Include(ur => ur.Role)
            .ThenInclude(r => r.RolePermissions)
            .ThenInclude(rp => rp.Permission)
            .Where(ur => ur.UserId == userId)
            .Any(ur => ur.Role.RolePermissions.Any(rp => 
                rp.Permission.Action == action && 
                rp.Permission.Resource == resource));
    }
    
    public List<Permission> GetUserPermissions(int userId)
    {
        return _db.UserRoles
            .Include(ur => ur.Role)
            .ThenInclude(r => r.RolePermissions)
            .ThenInclude(rp => rp.Permission)
            .Where(ur => ur.UserId == userId)
            .SelectMany(ur => ur.Role.RolePermissions.Select(rp => rp.Permission))
            .Distinct()
            .ToList();
    }
}

3.3 权限中间件

public class PermissionMiddleware
{
    private readonly RequestDelegate _next;
    
    public async Task Invoke(HttpContext context, PermissionService permissionService)
    {
        var userId = context.User.GetUserId();
        
        var endpoint = context.GetEndpoint();
        var attribute = endpoint?.Metadata.GetMetadata<RequirePermissionAttribute>();
        
        if (attribute != null && !permissionService.HasPermission(userId, attribute.Action, attribute.Resource))
        {
            context.Response.StatusCode = StatusCodes.Status403Forbidden;
            await context.Response.WriteAsync("Forbidden");
            return;
        }
        
        await _next(context);
    }
}

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
public class RequirePermissionAttribute : Attribute
{
    public string Action { get; }
    public string Resource { get; }
    
    public RequirePermissionAttribute(string action, string resource)
    {
        Action = action;
        Resource = resource;
    }
}

四、数据脱敏

4.1 数据脱敏概述

数据脱敏是对敏感数据进行处理,使其在非生产环境中不可识别:

脱敏类型 示例 适用场景
掩码 138****8888 手机号、身份证号
替换 test@example.com 邮箱、姓名
加密 AES加密后的数据 密码、银行卡号
删除 NULL 不需要的敏感字段

4.2 数据脱敏实现

public class DataMaskingService
{
    public string MaskPhone(string phone)
    {
        if (string.IsNullOrEmpty(phone) || phone.Length < 7)
            return phone;
        
        return phone.Substring(0, 3) + "****" + phone.Substring(phone.Length - 4);
    }
    
    public string MaskEmail(string email)
    {
        if (string.IsNullOrEmpty(email))
            return email;
        
        var atIndex = email.IndexOf('@');
        if (atIndex <= 1)
            return email;
        
        return email[0] + "***" + email.Substring(atIndex);
    }
    
    public string MaskIdCard(string idCard)
    {
        if (string.IsNullOrEmpty(idCard) || idCard.Length < 10)
            return idCard;
        
        return idCard.Substring(0, 4) + "**********" + idCard.Substring(idCard.Length - 4);
    }
    
    public string MaskBankCard(string bankCard)
    {
        if (string.IsNullOrEmpty(bankCard) || bankCard.Length < 12)
            return bankCard;
        
        return "**** **** **** " + bankCard.Substring(bankCard.Length - 4);
    }
}

4.3 EF Core数据脱敏

public class UserEntityTypeConfiguration : IEntityTypeConfiguration<User>
{
    public void Configure(EntityTypeBuilder<User> builder)
    {
        builder.Property(u => u.Phone)
            .HasConversion(
                phone => phone,
                phone => new DataMaskingService().MaskPhone(phone)
            );
        
        builder.Property(u => u.Email)
            .HasConversion(
                email => email,
                email => new DataMaskingService().MaskEmail(email)
            );
    }
}

五、行级安全

5.1 行级安全概述

行级安全(Row-Level Security)限制用户只能访问特定行的数据:

graph TD A[用户A] --> B[只能看到自己的数据] C[用户B] --> D[只能看到自己的数据] E[管理员] --> F[可以看到所有数据] G[数据表] --> B G --> D G --> F

5.2 PostgreSQL行级安全

-- 创建策略
CREATE POLICY user_data_policy ON users
    FOR ALL TO authenticated
    USING (id = current_setting('app.current_user_id')::int);

-- 启用行级安全
ALTER TABLE users ENABLE ROW LEVEL SECURITY;

-- 设置当前用户
SET app.current_user_id = '1';

-- 查询只能看到自己的数据
SELECT * FROM users;

5.3 MySQL行级安全

-- 创建视图实现行级安全
CREATE VIEW user_orders AS
    SELECT * FROM orders
    WHERE user_id = CURRENT_USER_ID();

-- 用户只能通过视图访问数据
GRANT SELECT ON user_orders TO app_user;

-- 禁止直接访问表
REVOKE ALL ON orders FROM app_user;

5.4 应用层行级安全

public class OrderRepository
{
    public List<Order> GetOrdersByUser(int userId)
    {
        return _db.Orders
            .Where(o => o.UserId == userId)
            .ToList();
    }
    
    public Order GetOrderById(int orderId, int userId)
    {
        return _db.Orders
            .SingleOrDefault(o => o.Id == orderId && o.UserId == userId);
    }
}

六、ABAC权限模型

6.1 ABAC概述

ABAC(Attribute-Based Access Control)是基于属性的访问控制模型:

graph TD A[用户属性] --> B[访问控制] C[资源属性] --> B D[环境属性] --> B A --> A1[角色、部门、级别] C --> C1[类型、位置、等级] D --> D1[时间、地点、设备] B --> E{策略评估} E --> F[允许访问] E --> G[拒绝访问]

6.2 ABAC策略

// ABAC策略示例
{
    "policy": "order_access",
    "rules": [
        {
            "condition": "user.department == resource.department",
            "effect": "allow"
        },
        {
            "condition": "user.role == 'manager'",
            "effect": "allow"
        },
        {
            "condition": "user.level >= 5",
            "effect": "allow"
        }
    ]
}

6.3 ABAC vs RBAC

特性 RBAC ABAC
灵活性
复杂度
性能 较低
适用场景 企业应用 复杂场景

七、权限审计

7.1 审计日志

-- 审计日志表
CREATE TABLE audit_logs (
    id INT PRIMARY KEY AUTO_INCREMENT,
    user_id INT,
    action VARCHAR(50),
    resource VARCHAR(50),
    resource_id INT,
    before_data JSON,
    after_data JSON,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

-- 记录审计日志
public void LogAudit(int userId, string action, string resource, int resourceId, object before, object after)
{
    _db.AuditLogs.Add(new AuditLog
    {
        UserId = userId,
        Action = action,
        Resource = resource,
        ResourceId = resourceId,
        BeforeData = JsonSerializer.Serialize(before),
        AfterData = JsonSerializer.Serialize(after)
    });
    _db.SaveChanges();
}

八、权限最佳实践

8.1 最小权限原则

只授予用户完成工作所需的最小权限。

8.2 权限分级

将权限分为不同级别,便于管理。

8.3 定期审查

定期审查用户权限,移除不必要的权限。

8.4 使用缓存

缓存用户权限,减少数据库查询。

8.5 日志记录

记录所有权限操作,便于审计。

九、总结

RBAC是企业级应用中最常用的权限模型,通过角色管理用户权限。数据脱敏和行级安全能够保护敏感数据,ABAC提供更灵活的访问控制。合理设计权限系统,能够构建安全可靠的数据密集型应用。