当前位置: 首页 > news >正文

Spring Boot 简单接口角色授权检查实现

一、背景与目标

在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 {// 可以注入需要的服务(如用户服务)@Autowiredprivate UserService userService;@Overridepublic 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 {@Autowiredprivate PermissionInterceptor permissionInterceptor;@Overridepublic 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";}
}

四、方案特点与优势

  1. 简单直接:无需复杂配置,快速实现权限控制

  2. 灵活可控:可以自由定义权限标识和检查逻辑

  3. 易于扩展:可以方便地替换为从数据库检查权限

  4. 符合RESTful:返回标准的HTTP状态码(403 Forbidden)

  5. 低侵入性:只需要添加注解,不影响业务逻辑代码

五、进阶优化方向

  1. 结合JWT:从token中解析用户角色和权限

  2. 缓存优化:缓存用户权限数据,减少数据库查询

  3. 动态权限:实现权限的动态配置和管理

  4. 日志记录:记录权限验证失败的访问尝试

  5. 白名单:添加无需权限检查的接口白名单

六、测试验证

可以使用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等专业安全框架。

http://www.lryc.cn/news/603834.html

相关文章:

  • C++入门知识学习(上)
  • 嵌入式学习日志(十一)
  • css3之三维变换详说
  • SQL Server中的分页查询
  • leetcode热题——螺旋矩阵
  • 第十一天:不定方程求解
  • 镁金属接骨螺钉注册检测:骨科植入安全的科学基石
  • Rust基础-part8-模式匹配、常见集合
  • 亚马逊 Vine 计划:评论生态重构与合规运营策略
  • 学习笔记-中华心法问答系统的性能提升
  • 小孙学变频学习笔记(十二)机械特性的调整 机械特性的改善
  • 想要批量提取视频背景音乐?FFmpeg 和转换器都安排上
  • Day 25:异常处理
  • VTK开发笔记(一):VTK介绍,Qt5.9.3+VS2017x64+VTK8.2编译
  • Zynq SOC FPGA嵌入式裸机设计和开发教程自学笔记:GPIO扩展与中断控制技术,万字详解!!
  • 车载刷写架构 --- 整车刷写中为何增加了ECU 队列刷写策略?
  • 服务器分布式的作用都有什么?
  • Windows下基于 SenseVoice模型的本地语音转文字工具
  • Ubuntu25.04轻量虚拟机Multipass使用Shell脚本自动创建并启动不同版本Ubuntu并复制文件
  • 【支持Ubuntu22】Ambari3.0.0+Bigtop3.2.0——Step1—基础环境准备
  • GaussDB 约束的语法
  • 【LeetCode】前缀表相关算法
  • 服务器数据恢复—RAID上层部署的oracle数据库数据恢复案例
  • Node.js 是怎么一步步撼动PHP地位的
  • #C语言——学习攻略:深挖指针路线(三)--数组与指针的结合、冒泡排序
  • 云原生MySQL Operator开发实战(四):测试策略与生产部署
  • 什么情况下会出现数据库和缓存不一致的问题?
  • PowerShell脚本自动卸载SQL Server 2025和 SSMS
  • 传媒行业视频制作:物理服务器租用是隐藏的效率引擎
  • 基于Coze平台的自动化情报采集与处理引擎—实现小红书图文到飞书的端到端同步