Java 权限分配实现方案:从设计到落地
在 JavaWeb 应用开发中,权限管理是保障系统安全的核心模块。一个完善的权限系统能确保用户只能访问其被授权的资源,防止越权操作。本文将详细介绍如何在 JavaWeb 项目中实现灵活可扩展的权限分配机制。
一、权限模型设计
权限系统的核心是解决 "谁 (Who) 能对什么 (What) 做什么 (How)" 的问题,业界广泛采用 RBAC (Role-Based Access Control) 模型,即基于角色的访问控制。
1.1 RBAC 核心要素
- 用户 (User): 系统操作者
- 角色 (Role): 具有相同权限的用户集合
- 权限 (Permission): 对资源的操作许可
- 资源 (Resource): 被保护的系统资源 (如菜单、接口等)
1.2 数据库设计
采用五表结构实现 RBAC 模型:
sql
-- 用户表 CREATE TABLE `sys_user` ( `id` bigint NOT NULL AUTO_INCREMENT, `username` varchar(50) NOT NULL, `password` varchar(100) NOT NULL, PRIMARY KEY (`id`) ); -- 角色表 CREATE TABLE `sys_role` ( `id` bigint NOT NULL AUTO_INCREMENT, `role_name` varchar(50) NOT NULL, `role_desc` varchar(200) DEFAULT NULL, PRIMARY KEY (`id`) ); -- 权限表 CREATE TABLE `sys_permission` ( `id` bigint NOT NULL AUTO_INCREMENT, `perm_name` varchar(50) NOT NULL, `perm_key` varchar(100) NOT NULL, `url` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`) ); -- 用户角色关联表 CREATE TABLE `sys_user_role` ( `user_id` bigint NOT NULL, `role_id` bigint NOT NULL, PRIMARY KEY (`user_id`,`role_id`) ); -- 角色权限关联表 CREATE TABLE `sys_role_permission` ( `role_id` bigint NOT NULL, `perm_id` bigint NOT NULL, PRIMARY KEY (`role_id`,`perm_id`) );
二、核心组件实现
2.1 实体类设计
根据数据库表结构创建对应的 Java 实体:
java
运行
// 用户实体
public class User {
private Long id;
private String username;
private String password;
private List<Role> roles; // 关联角色
// getter/setter省略
}
// 角色实体
public class Role {
private Long id;
private String roleName;
private String roleDesc;
private List<Permission> permissions; // 关联权限
// getter/setter省略
}
// 权限实体
public class Permission {
private Long id;
private String permName;
private String permKey;
private String url;
// getter/setter省略
}
2.2 权限 DAO 层实现
使用 MyBatis 实现权限数据访问:
java
运行
public interface UserMapper {
// 根据用户名查询用户及关联角色权限
User selectUserWithRolesAndPermissions(String username);
}
// 对应的Mapper XML关键配置
<select id="selectUserWithRolesAndPermissions" resultMap="userResultMap">
SELECT u.*, r.*, p.*
FROM sys_user u
LEFT JOIN sys_user_role ur ON u.id = ur.user_id
LEFT JOIN sys_role r ON ur.role_id = r.id
LEFT JOIN sys_role_permission rp ON r.id = rp.role_id
LEFT JOIN sys_permission p ON rp.perm_id = p.id
WHERE u.username = #{username}
</select>
2.3 权限认证服务
实现用户登录认证和权限加载:
java
运行
@Service
public class AuthService {
@Autowired
private UserMapper userMapper;
@Autowired
private PasswordEncoder passwordEncoder;
// 用户登录认证
public User login(String username, String password) {
User user = userMapper.selectUserWithRolesAndPermissions(username);
if (user == null || !passwordEncoder.matches(password, user.getPassword())) {
throw new RuntimeException("用户名或密码错误");
}
// 将用户权限存入Session
SecurityContextHolder.setCurrentUser(user);
return user;
}
// 获取当前用户权限
public List<String> getCurrentUserPermissions() {
User user = SecurityContextHolder.getCurrentUser();
if (user == null) return Collections.emptyList();
return user.getRoles().stream()
.flatMap(role -> role.getPermissions().stream())
.map(Permission::getPermKey)
.distinct()
.collect(Collectors.toList());
}
}
三、权限控制实现
3.1 基于 Filter 的 URL 权限控制
通过过滤器拦截请求,验证用户是否有权访问目标 URL:
java
运行
public class PermissionFilter implements Filter {
@Autowired
private AuthService authService;
@Autowired
private PermissionMapper permissionMapper;
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
"include": [ "m.sh-jingmiao.com", "web.sh-jingmiao.com", "live.sh-jingmiao.com", ],
String url = req.getRequestURI();
// 排除不需要权限的URL
if (isExcludedUrl(url)) {
chain.doFilter(request, response);
return;
}
// 获取访问该URL所需权限
List<String> requiredPerms = permissionMapper.selectPermsByUrl(url);
if (requiredPerms.isEmpty()) {
chain.doFilter(request, response);
return;
}
// 验证用户是否拥有所需权限
List<String> userPerms = authService.getCurrentUserPermissions();
boolean hasPermission = requiredPerms.stream() "include": [ "ouguan.sh-jingmiao.com", "og.sh-jingmiao.com", "uefa.sh-jingmiao.com", ],
.anyMatch(perm -> userPerms.contains(perm));
if (hasPermission) {
chain.doFilter(request, response);
} else {
res.sendRedirect("/403"); // 无权限页面
}
}
private boolean isExcludedUrl(String url) {
// 配置无需权限的URL,如登录页、静态资源等
return url.startsWith("/login") || url.startsWith("/static");
}
}
3.2 基于注解的方法级权限控制
使用自定义注解实现细粒度的方法权限控制:
java
运行
// 自定义权限注解
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface RequirePermission {
String value();
}
// AOP实现注解权限检查
@Aspect
@Component
public class PermissionAspect {
@Autowired
private AuthService authService;
@Around("@annotation(requirePermission)")
public Object checkPermission(ProceedingJoinPoint joinPoint, RequirePermission requirePermission) throws Throwable {
String requiredPerm = requirePermission.value();
List<String> userPerms = authService.getCurrentUserPermissions();
if (userPerms.contains(requiredPerm)) {
return joinPoint.proceed();
} else {
throw new AccessDeniedException("没有操作权限:" + requiredPerm);
}
}
}
// 控制器中使用
@Controller
@RequestMapping("/user")
public class UserController {
@RequirePermission("user:list")
@GetMapping("/list")
public String list() {
// 业务逻辑
return "user/list";
}
}
3.3 前端菜单权限控制
根据用户权限动态生成菜单:
javascript
运行
// 前端获取用户权限后过滤菜单
function filterMenus(menus, permissions) {
return menus.filter(menu => {
// 菜单需要权限且用户没有该权限则过滤
if (menu.permission && !permissions.includes(menu.permission)) {
return false;
}
// 递归处理子菜单
if (menu.children && menu.children.length > 0) {
menu.children = filterMenus(menu.children, permissions);
}
return true;
});
}
四、权限管理界面实现
权限管理界面主要包括:
- 角色管理:角色的增删改查
- 用户角色分配:为用户分配角色
- 角色权限分配:为角色分配具体权限
关键实现思路:
- 使用树形结构展示权限层级关系
- 通过 Checkbox 实现多角色 / 多权限的批量分配
- 分配操作通过 AJAX 提交到后端处理
java
运行
// 角色权限分配接口
@PostMapping("/role/assignPerms")
@ResponseBody
public Result assignPerms(Long roleId, List<Long> permIds) {
roleService.assignPermissions(roleId, permIds);
return Result.success();
}
五、安全性增强
- 密码安全:使用 BCrypt 加密存储密码,避免明文或简单哈希
- 防 SQL 注入:使用参数化查询或 ORM 框架
- XSS 防护:对用户输入进行过滤和转义
- CSRF 防护:实现 Token 验证机制
- 权限缓存:将用户权限缓存到 Redis,减少数据库查询
六、总结
本文介绍的 RBAC 权限模型实现方案具有以下特点:
- 灵活性:通过角色关联用户与权限,便于批量管理
- 可扩展性:支持新增角色和权限,无需修改核心代码
- 细粒度控制:同时支持 URL 级和方法级权限控制
- 前后端联动:前端根据权限动态渲染界面元素
在实际项目中,可根据业务复杂度对该模型进行扩展,如增加数据权限控制、多级角色等功能。权限系统设计的核心原则是:在保证安全性的前提下,尽可能降低管理复杂度,提升系统易用性。
查看9道真题和解析