一、背景与目标
在Spring Boot应用开发中,接口级别的权限控制是系统安全的重要组成部分。本文将介绍一种简单直接的接口角色授权检查实现方案,适合快速开发和安全合规检查场景。
二、技术方案概述
本方案采用自定义注解+拦截器的方式实现,具有以下特点:
零依赖(不引入Spring Security等重型框架)
代码简洁(总共不到100行核心代码)
易于理解和使用
满足基本的安全检查要求
三、完整实现步骤
1. 创建权限注解
import java.lang.annotation.*;
/**
* 权限检查注解
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RequiredPermission {
String value(); // 权限标识符,如"user:add"
}
2. 实现权限拦截器
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
/**
* 权限检查拦截器
*/
@Component
public class PermissionInterceptor implements HandlerInterceptor {
// 可以注入需要的服务(如用户服务)
@Autowired
private UserService userService;
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) throws Exception {
if (!(handler instanceof HandlerMethod)) {
return true;
}
HandlerMethod handlerMethod = (HandlerMethod) handler;
Method method = handlerMethod.getMethod();
// 获取方法上的权限注解
RequiredPermission permission = method.getAnnotation(RequiredPermission.class);
if (permission == null) {
return true; // 无权限注解则放行
}
String requiredPermission = permission.value();
String token = request.getHeader("Authorization");
// 实际项目中应从token解析用户信息,这里简化为直接判断
boolean hasPermission = checkPermission(token, requiredPermission);
if (!hasPermission) {
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
response.getWriter().write("Access denied: Required permission - " + requiredPermission);
return false;
}
return true;
}
private boolean checkPermission(String token, String requiredPermission) {
// 这里写死检查逻辑,实际项目应从数据库或缓存获取用户权限
if ("admin-token".equals(token)) {
return true; // 管理员有所有权限
} else if ("user-token".equals(token)) {
return !"user:add".equals(requiredPermission); // 普通用户不能新增用户
}
return false;
}
}
3. 注册拦截器
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Autowired
private PermissionInterceptor permissionInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(permissionInterceptor)
.addPathPatterns("/api/**"); // 拦截/api开头的请求
}
}
4. 在Controller中使用
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api/user")
public class UserController {
@PostMapping
@RequiredPermission("user:add")
public String addUser() {
return "User added successfully";
}
@GetMapping
@RequiredPermission("user:view")
public String listUsers() {
return "User list";
}
@PutMapping("/{id}")
@RequiredPermission("user:edit")
public String updateUser(@PathVariable Long id) {
return "User updated";
}
@DeleteMapping("/{id}")
@RequiredPermission("user:delete")
public String deleteUser(@PathVariable Long id) {
return "User deleted";
}
}
四、方案特点与优势
简单直接:无需复杂配置,快速实现权限控制
灵活可控:可以自由定义权限标识和检查逻辑
易于扩展:可以方便地替换为从数据库检查权限
符合RESTful:返回标准的HTTP状态码(403 Forbidden)
低侵入性:只需要添加注解,不影响业务逻辑代码
五、进阶优化方向
结合JWT:从token中解析用户角色和权限
缓存优化:缓存用户权限数据,减少数据库查询
动态权限:实现权限的动态配置和管理
日志记录:记录权限验证失败的访问尝试
白名单:添加无需权限检查的接口白名单
六、测试验证
可以使用Postman或curl进行测试:
# 管理员可以访问所有接口
curl -X POST -H "Authorization: admin-token" http://localhost:8080/api/user
# 普通用户不能访问添加接口
curl -X POST -H "Authorization: user-token" http://localhost:8080/api/user
# 返回: Access denied: Required permission - user:add
# 普通用户可以访问查看接口
curl -X GET -H "Authorization: user-token" http://localhost:8080/api/user
# 返回: User list
七、总结
本文介绍的Spring Boot接口权限控制方案虽然简单,但包含了权限控制的核心要素,能够满足基本的安全需求。对于快速开发和小型项目来说,这是一个轻量级且有效的解决方案。对于更复杂的企业级应用,建议在此基础上进行扩展或考虑使用Spring Security等专业安全框架。