授权模型
RBAC、ABAC 与 ReBAC。
授权模型
这一课你将能做到
- 实现 RBAC(基于角色的访问控制),设计用户-角色-权限三层模型
- 理解 ABAC(基于属性的访问控制)和 ReBAC(基于关系的访问控制)的适用场景
- 在 Spring Security 中配置方法级和 URL 级权限控制
为什么要学
认证解决「你是谁」,授权解决「你能做什么」。一个系统里,管理员能删课程、讲师能改课程内容、学员只能看——这就是授权。授权模型选错,要么权限漏洞导致越权,要么设计过度复杂拖慢开发。
先建立图像
RBAC 模型(最常用):
┌────────┐ ┌────────┐ ┌────────┐
│ 用户 │ ───► │ 角色 │ ───► │ 权限 │
│ User │ │ Role │ │Permission│
└────────┘ └────────┘ └────────┘
张三 管理员 课程:删除
李四 讲师 课程:编辑
王五 学员 课程:查看
ABAC 模型(更灵活):
用户属性(部门=技术部, 级别=P7) + 资源属性(密级=机密) + 环境属性(时间=工作日)
│
▼
策略引擎判断:技术部 P7 以上 + 工作日 → 允许访问机密文件
ReBAC 模型(社交关系):
用户A ──关注──► 用户B ──发布──► 文章X
│
└── 因为关注关系,A 可以查看 B 的文章
跟着做
步骤 1:数据库设计(RBAC)
-- 用户表
CREATE TABLE users (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50) UNIQUE NOT NULL,
password VARCHAR(100) NOT NULL,
email VARCHAR(100)
);
-- 角色表
CREATE TABLE roles (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
code VARCHAR(50) UNIQUE NOT NULL, -- ADMIN, INSTRUCTOR, STUDENT
name VARCHAR(100) NOT NULL
);
-- 权限表
CREATE TABLE permissions (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
code VARCHAR(100) UNIQUE NOT NULL, -- lesson:read, lesson:write, lesson:delete
name VARCHAR(100) NOT NULL,
resource VARCHAR(50), -- lesson, submission, user
action VARCHAR(50) -- read, write, delete
);
-- 用户-角色关联
CREATE TABLE user_roles (
user_id BIGINT,
role_id BIGINT,
PRIMARY KEY (user_id, role_id)
);
-- 角色-权限关联
CREATE TABLE role_permissions (
role_id BIGINT,
permission_id BIGINT,
PRIMARY KEY (role_id, permission_id)
);
步骤 2:实体类
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String username;
private String password;
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(name = "user_roles",
joinColumns = @JoinColumn(name = "user_id"),
inverseJoinColumns = @JoinColumn(name = "role_id"))
private Set<Role> roles = new HashSet<>();
}
@Entity
@Table(name = "roles")
public class Role {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String code;
private String name;
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(name = "role_permissions",
joinColumns = @JoinColumn(name = "role_id"),
inverseJoinColumns = @JoinColumn(name = "permission_id"))
private Set<Permission> permissions = new HashSet<>();
}
@Entity
@Table(name = "permissions")
public class Permission {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String code;
private String name;
private String resource;
private String action;
}