本文目录导读:

- 基于RBAC(基于角色的访问控制)
- 基于Spring Security + JWT的权限控制
- 基于注解的细粒度权限控制(方法级别)
- 基于过滤器链的URL级别权限控制
- 基于ABAC(基于属性的访问控制)
- 最佳实践建议
- 实际项目案例结构
在Java中实现权限控制,通常有几种主流方案,具体选择取决于你的应用类型(单体应用、微服务、分布式系统)和安全级别需求,以下是几种最常用的实现方式及案例:
基于RBAC(基于角色的访问控制)
这是最常见也是最成熟的权限控制模型。
核心思想:
- 用户(User):系统的使用者
- 角色(Role):权限的集合(如管理员、普通用户)
- 权限(Permission):具体的操作许可(如创建文章、删除用户)
数据结构设计:
-- 用户表
CREATE TABLE `sys_user` (
`id` BIGINT PRIMARY KEY AUTO_INCREMENT,
`username` VARCHAR(50) NOT NULL,
`password` VARCHAR(100) NOT NULL
);
-- 角色表
CREATE TABLE `sys_role` (
`id` BIGINT PRIMARY KEY AUTO_INCREMENT,
`role_name` VARCHAR(50) NOT NULL,
`role_code` VARCHAR(50) NOT NULL UNIQUE
);
-- 权限表
CREATE TABLE `sys_permission` (
`id` BIGINT PRIMARY KEY AUTO_INCREMENT,
`perm_name` VARCHAR(50) NOT NULL,
`perm_code` VARCHAR(50) NOT NULL UNIQUE -- 如 "user:create"
);
-- 用户-角色关系表
CREATE TABLE `sys_user_role` (
`user_id` BIGINT,
`role_id` BIGINT,
PRIMARY KEY (`user_id`, `role_id`)
);
-- 角色-权限关系表
CREATE TABLE `sys_role_permission` (
`role_id` BIGINT,
`permission_id` BIGINT,
PRIMARY KEY (`role_id`, `permission_id`)
);
Spring Security + RBAC 实现示例:
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(auth -> auth
// 基于权限码控制
.requestMatchers("/api/user/create").hasAuthority("user:create")
.requestMatchers("/api/user/delete").hasAuthority("user:delete")
// 基于角色控制(注意角色需要加ROLE_前缀)
.requestMatchers("/api/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
)
.formLogin(Customizer.withDefaults());
return http.build();
}
}
基于Spring Security + JWT的权限控制
适用于前后端分离的单体或微服务架构。
实现流程:
// 1. JWT Token工具类
@Component
public class JwtTokenUtil {
public String generateToken(UserDetails userDetails) {
Map<String, Object> claims = new HashMap<>();
// 将用户的角色和权限加入JWT
claims.put("roles", userDetails.getAuthorities());
return Jwts.builder()
.setClaims(claims)
.setSubject(userDetails.getUsername())
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + 3600000))
.signWith(SignatureAlgorithm.HS512, "secret")
.compact();
}
}
// 2. JWT认证过滤器
public class JwtAuthenticationFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain chain) {
String token = request.getHeader("Authorization");
if (token != null) {
// 解析token并设置SecurityContext
Authentication auth = jwtTokenUtil.parseToken(token);
SecurityContextHolder.getContext().setAuthentication(auth);
}
chain.doFilter(request, response);
}
}
基于注解的细粒度权限控制(方法级别)
使用Spring的@PreAuthorize注解实现方法级别的权限控制:
@RestController
@RequestMapping("/api/users")
public class UserController {
// 基于角色控制
@PreAuthorize("hasRole('ADMIN')")
@GetMapping("/all")
public List<User> getAllUsers() {
return userService.findAll();
}
// 基于权限码控制
@PreAuthorize("hasAuthority('user:create')")
@PostMapping
public User createUser(@RequestBody User user) {
return userService.create(user);
}
// 基于表达式控制(用户只能操作自己的数据)
@PreAuthorize("#id == authentication.principal.id or hasRole('ADMIN')")
@PutMapping("/{id}")
public User updateUser(@PathVariable Long id, @RequestBody User user) {
return userService.update(id, user);
}
}
// 启用方法级别的安全控制
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MethodSecurityConfig {
// 配置类
}
基于过滤器链的URL级别权限控制
适用于前后端分离的项目,在网关或应用层进行统一拦截:
@Component
public class PermissionFilter implements Filter {
@Autowired
private PermissionService permissionService;
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) {
HttpServletRequest httpRequest = (HttpServletRequest) request;
String requestURI = httpRequest.getRequestURI();
String method = httpRequest.getMethod();
// 获取当前用户权限
User currentUser = getCurrentUser();
// 检查用户是否有访问该URL的权限
if (permissionService.checkPermission(currentUser, method, requestURI)) {
chain.doFilter(request, response);
} else {
// 返回403禁止访问
response.getWriter().write("Access Denied");
}
}
}
基于ABAC(基于属性的访问控制)
适用于更复杂的业务场景,支持基于用户属性、环境属性、资源属性进行动态决策:
public class ABACPolicyEngine {
public boolean evaluate(Policy policy, Subject subject, Resource resource, Environment env) {
// 示例规则:只有创建者或管理员可以删除文档
return policy.getRules().stream().anyMatch(rule -> {
if (rule.getAction().equals("delete_document")) {
// 检查用户是否为管理员
boolean isAdmin = subject.hasRole("ADMIN");
// 检查用户是否为文档创建者
boolean isOwner = resource.getAttribute("ownerId").equals(subject.getId());
return isAdmin || isOwner;
}
return false;
});
}
}
最佳实践建议
-
选择合适粒度:
- URL级别:适合统一的权限拦截,性能好
- 方法级别:更精细的控制,适合复杂业务
- 数据级别:控制到具体的数据行(如用户只能看自己创建的数据)
-
缓存策略:
@Service public class PermissionService { @Cacheable(value = "userPermissions", key = "#userId") public Set<String> getUserPermissions(Long userId) { // 此处查询数据库获取用户所有权限 return permissionDAO.findByUserId(userId); } } -
性能优化:
- 权限数据使用Redis缓存
- 使用Bloom Filter进行快速权限判断
- 避免在循环中重复查询权限
-
安全考虑:
- 前端只显示用户有权限的菜单/按钮(体验优化,但不可作为安全依据)
- 后端必须做全面的权限校验(前端限制不安全)
- 防止权限绕过(如修改URL参数、篡改请求方式等)
实际项目案例结构
// 一个完整的权限校验服务
@Service
public class AccessControlService {
// 检查是否有某个操作权限
public boolean hasPermission(String permissionCode) {
// 获取当前登录用户
User currentUser = getCurrentUser();
// 超级管理员拥有所有权限
if (currentUser.isSuperAdmin()) {
return true;
}
// 从缓存或数据库获取用户权限列表
Set<String> permissions = getUserPermissions(currentUser.getId());
return permissions.contains(permissionCode);
}
// 检查是否拥有某个角色
public boolean hasRole(String roleCode) {
User currentUser = getCurrentUser();
return currentUser.getRoles().stream()
.anyMatch(role -> role.getRoleCode().equals(roleCode));
}
// 检查是否拥有所有指定权限(AND逻辑)
public boolean hasAllPermissions(String... permissionCodes) {
return Arrays.stream(permissionCodes)
.allMatch(this::hasPermission);
}
// 检查是否拥有任一指定权限(OR逻辑)
public boolean hasAnyPermission(String... permissionCodes) {
return Arrays.stream(permissionCodes)
.anyMatch(this::hasPermission);
}
}
选择哪种方式取决于你的具体需求:如果是简单的管理后台,RBAC通常足够;如果是复杂的多租户SaaS系统,可能需要ABAC;如果追求开发效率,直接用Spring Security的注解方式即可,建议从简单开始,逐步演进,避免过度设计。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播