基于Spring Boot的权限控制系统实现
在企业级应用开发中,权限管理是保障系统安全的核心环节。不同角色的用户需要访问不同的功能模块,例如财务部门只能访问财务相关功能,而销售部门则只能访问销售模块。本文将介绍如何通过Spring Boot的拦截器机制实现灵活的权限控制系统。
系统设计采用用户-角色-权限的三层结构,每个用户拥有多个角色,每个角色又关联多个具体权限。
数据库表结构

拦截器配置
WebMvcConfig
@Configuration
public class WebMvcConfig extends WebMvcConfigurationSupport {
@Autowired
private AccessControlInterceptor accessControlInterceptor;
@Bean
public CustomInterceptor customInterceptor() {
return new CustomInterceptor();
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(accessControlInterceptor);
registry.addInterceptor(customInterceptor())
.addPathPatterns("/**")
.addPathPatterns("/admin/**")
.excludePathPatterns("/swagger-resources/**", "/webjars/**", "/v2/**", "/swagger-ui.html/**", "/config/**");
super.addInterceptors(registry);
}
@Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("swagger-ui.html")
.addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/");
}
@Bean
public ErrorProperties errorProperties() {
final ErrorProperties properties = new ErrorProperties();
properties.setIncludeStacktrace(IncludeStacktrace.ALWAYS);
return properties;
}
@Bean
public HttpMessageConverters fastJsonHttpMessageConverters() {
FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();
FastJsonConfig fastJsonConfig = new FastJsonConfig();
fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat);
fastConverter.setFastJsonConfig(fastJsonConfig);
return new HttpMessageConverters(fastConverter);
}
@Bean(name = "multipartResolver")
public MultipartResolver multipartResolver() {
CommonsMultipartResolver resolver = new CommonsMultipartResolver();
resolver.setDefaultEncoding("UTF-8");
resolver.setResolveLazily(true);
resolver.setMaxInMemorySize(40960);
resolver.setMaxUploadSize(5 * 1024 * 1024);
return resolver;
}
}
CustomInterceptor
@Component
public class CustomInterceptor implements HandlerInterceptor {
private static final Logger logger = LoggerFactory.getLogger(CustomInterceptor.class);
@Autowired
AccessControlService accessControlService;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
accessControlService.test();
System.out.println(accessControlService.test());
System.out.println(request);
System.out.println(response);
System.out.println(handler);
if (accessControlService.verifyAccess(request, response, handler)) {
return true;
}
response.sendError(HttpStatus.FORBIDDEN.value(), "无访问权限");
HandlerMethod handlerMethod = (HandlerMethod) handler;
Method method = handlerMethod.getMethod();
String methodName = method.getName();
logger.info("拦截到方法:{},执行前验证", methodName);
return false;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
logger.info("方法执行完成,视图渲染前");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
logger.info("请求处理完成,视图已渲染");
}
}
权限常量定义
AccessPermissionConstants
public class AccessPermissionConstants {
// 商品管理权限
public static final String PRODUCT_LIST = "product_list_query";
public static final String PRODUCT_DELETE = "product_delete";
public static final String PRODUCT_CREATE = "product_create";
public static final String PRODUCT_MODIFY = "product_modify";
// 角色管理权限
public static final String ROLE_LIST = "role_list_query";
public static final String ROLE_CREATE = "role_create";
public static final String ROLE_MODIFY = "role_modify";
public static final String ROLE_DELETE = "role_delete";
// 商品类目权限
public static final String CATEGORY_LIST = "category_list_query";
public static final String CATEGORY_CREATE = "category_create";
public static final String CATEGORY_MODIFY = "category_modify";
public static final String CATEGORY_DELETE = "category_delete";
// 会员管理权限
public static final String MEMBER_LIST = "member_list_query";
public static final String MEMBER_DELETE = "member_delete";
public static final String MEMBER_CREATE = "member_create";
public static final String MEMBER_MODIFY = "member_modify";
// 资产管理权限
public static final String PROPERTY_LIST = "property_list_query";
public static final String PROPERTY_DETAIL = "property_detail_view";
public static final String PROPERTY_WITHDRAW = "property_withdraw";
// 活动管理权限
public static final String ACTIVITY_LIST = "activity_list_query";
public static final String ACTIVITY_DETAIL = "activity_detail_view";
public static final String ACTIVITY_ACTIVATE = "activity_activate";
public static final String ACTIVITY_CREATE = "activity_create";
public static final String ACTIVITY_MODIFY = "activity_modify";
public static final String ACTIVITY_DELETE = "activity_delete";
// 管理员权限
public static final String ADMIN_LIST = "admin_list_query";
public static final String ADMIN_MODIFY = "admin_modify";
}
权限注解定义
AccessPermission
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface AccessPermission {
String value();
}
权限验证服务实现
AccessControlServiceImpl
@Service
public class AccessControlServiceImpl implements AccessControlService {
@Autowired
private UserRoleMapper userRoleMapper;
@Autowired
private RolePermissionMapper rolePermissionMapper;
@Autowired
private PermissionMapper permissionMapper;
@Override
public boolean verifyAccess(HttpServletRequest request, HttpServletResponse response, Object handler) {
System.out.println("进入权限验证服务");
String userId = extractUserIdFromRequest(request);
if (userId == null) {
return false;
}
List<UserRole> userRoles = getUserRoles(userId);
if (userRoles.isEmpty()) {
return false;
}
Integer roleId = userRoles.get(0).getRoleId();
List<RolePermission> rolePermissions = getRolePermissions(roleId);
if (handler instanceof HandlerMethod) {
HandlerMethod handlerMethod = (HandlerMethod) handler;
// 获取方法上的注解
AccessPermission accessPermission = handlerMethod.getMethod().getAnnotation(AccessPermission.class);
// 如果方法上的注解为空,则获取类的注解
if (accessPermission == null) {
accessPermission = handlerMethod.getMethod().getDeclaringClass().getAnnotation(AccessPermission.class);
}
// 如果没有权限注解,则允许访问
if (accessPermission == null) {
return true;
}
// 如果标记了注解,则验证权限
if (accessPermission != null && StringUtils.isNotBlank(accessPermission.value())) {
if (rolePermissions.isEmpty()) {
return false;
}
for (RolePermission rolePermission : rolePermissions) {
Integer permissionId = rolePermission.getPermissionId();
Permission permission = permissionMapper.selectByPrimaryKey(permissionId);
if (accessPermission.value().equals(permission.getAccessCode())) {
return true;
}
}
return false;
}
}
return true;
}
private String extractUserIdFromRequest(HttpServletRequest request) {
String userId = "123";
Cookie[] cookies = request.getCookies();
if (cookies != null) {
for (Cookie cookie : cookies) {
if ("autologin".equals(cookie.getName())) {
userId = cookie.getValue();
break;
}
}
}
return userId;
}
private List<UserRole> getUserRoles(String userId) {
Example example = new Example(UserRole.class);
Example.Criteria criteria = example.createCriteria();
criteria.andEqualTo("userId", userId);
return userRoleMapper.selectByExample(example);
}
private List<RolePermission> getRolePermissions(Integer roleId) {
Example example = new Example(RolePermission.class);
Example.Criteria criteria = example.createCriteria();
criteria.andEqualTo("roleId", roleId);
return rolePermissionMapper.selectByExample(example);
}
@Override
public int test() {
System.out.println("测试方法调用");
return 0;
}
}
用户认证
登录时将用户ID存储在Cookie中,实现会话跟踪。后续可扩展为JWT Token支持分布式系统。
Cookie cookie = new Cookie("autologin", authKey);
cookie.setPath("/");
response.addCookie(cookie);
使用方法 在需要权限控制的接口或方法上添加注解:
@RestController
@RequestMapping("/admin/product")
public class ProductController {
@GetMapping("/list")
@AccessPermission(AccessPermissionConstants.PRODUCT_LIST)
public List<Product> getProductList() {
// 商品列表查询逻辑
return productService.getAllProducts();
}
@PostMapping("/create")
@AccessPermission(AccessPermissionConstants.PRODUCT_CREATE)
public Product createProduct(@RequestBody Product product) {
// 创建商品逻辑
return productService.addProduct(product);
}
}
通过以上实现,系统可以根据用户角色动态控制接口访问权限,确保不同用户只能访问其权限范围内的功能模块。