一、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提供更灵活的访问控制。合理设计权限系统,能够构建安全可靠的数据密集型应用。