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

别再只会用@PreAuthorize了!手把手教你用SpringBoot AOP+自定义注解+SpEL打造更灵活的权限控制

超越PreAuthorize用SpringBoot AOPSpEL构建动态权限控制体系在后台管理系统开发中权限控制是保障业务安全的核心环节。虽然Spring Security提供的PreAuthorize注解能够满足基础需求但面对仅工作日可访问、只能操作自己创建的数据等复杂场景时开发者往往需要更灵活的解决方案。本文将带你从零构建一套基于自定义注解、AOP和SpEL表达式的动态权限控制系统。1. 为什么需要超越PreAuthorizeSpring Security的PreAuthorize注解确实简化了权限验证流程但它存在三个明显局限业务耦合度高权限逻辑硬编码在注解中修改时需要重新编译动态能力有限难以实现基于时间、数据状态等条件的权限判断复用性差相似权限逻辑需要在多个地方重复编写// 传统方式的问题示例 PreAuthorize(hasRole(ADMIN) hasPermission(USER_MANAGE)) public void updateUser(User user) { // 业务逻辑 }当需求变为管理员只能在工作时间修改用户信息时这种静态表达式就显得力不从心。2. 核心组件设计2.1 自定义注解DynamicAuth我们首先定义一个功能更强大的注解Target({ElementType.METHOD, ElementType.TYPE}) Retention(RetentionPolicy.RUNTIME) public interface DynamicAuth { /** * SpEL表达式支持 * - 角色校验auth.checkRoles(ADMIN) * - 时间控制auth.isWorkTime() * - 数据权限auth.isOwner(#user.id) */ String value(); /** * 验证失败时的错误信息 */ String message() default 无操作权限; }相比PreAuthorize这个注解增加了自定义错误信息且表达式支持更丰富的语义。2.2 权限验证服务AuthService创建一个Spring组件来承载各种验证逻辑Service(auth) public class AuthService { private final UserRoleRepository roleRepository; // 检查是否拥有指定角色 public boolean checkRoles(String... roles) { User current getCurrentUser(); return Arrays.stream(roles) .anyMatch(role - roleRepository.existsByUserIdAndRole(current.getId(), role)); } // 是否在工作时间段9:00-18:00 public boolean isWorkTime() { LocalTime now LocalTime.now(); return now.isAfter(LocalTime.of(9, 0)) now.isBefore(LocalTime.of(18, 0)); } // 是否是数据所有者 public boolean isOwner(Long ownerId) { return Objects.equals(getCurrentUser().getId(), ownerId); } }2.3 AOP切面实现核心的权限拦截逻辑通过AOP实现Aspect Component RequiredArgsConstructor public class DynamicAuthAspect { private final AuthService authService; private final ExpressionParser parser new SpelExpressionParser(); Around(annotation(dynamicAuth) || within(dynamicAuth)) public Object checkAuth(ProceedingJoinPoint joinPoint, DynamicAuth dynamicAuth) throws Throwable { Method method ((MethodSignature) joinPoint.getSignature()).getMethod(); // 构建SpEL上下文 EvaluationContext context new StandardEvaluationContext(); context.setVariable(auth, authService); addMethodParameters(context, method, joinPoint.getArgs()); // 解析表达式 Expression expression parser.parseExpression(dynamicAuth.value()); if (Boolean.TRUE.equals(expression.getValue(context, Boolean.class))) { return joinPoint.proceed(); } throw new AccessDeniedException(dynamicAuth.message()); } private void addMethodParameters(EvaluationContext context, Method method, Object[] args) { ParameterNameDiscoverer discoverer new DefaultParameterNameDiscoverer(); String[] paramNames discoverer.getParameterNames(method); if (paramNames ! null) { for (int i 0; i paramNames.length; i) { context.setVariable(paramNames[i], args[i]); } } } }3. 实战应用场景3.1 时间敏感型权限实现工作时段才能提交审批的需求DynamicAuth( value auth.isWorkTime(), message 非工作时间不能提交审批 ) PostMapping(/approval) public Result submitApproval(RequestBody ApprovalRequest request) { // 审批逻辑 }3.2 数据关联型权限实现只能修改自己创建的订单DynamicAuth(#auth.isOwner(#order.createdBy)) PutMapping(/orders/{id}) public Result updateOrder(PathVariable Long id, RequestBody Order order) { // 更新逻辑 }3.3 复合条件权限组合多个条件的复杂权限校验DynamicAuth( value auth.checkRoles(DEPARTMENT_MANAGER) auth.isWorkTime() #auth.isOwner(#report.createdBy), message 不符合报表修改条件 ) PostMapping(/reports) public Result updateReport(RequestBody Report report) { // 报表更新逻辑 }4. 高级技巧与优化4.1 性能优化方案频繁解析SpEL表达式可能成为性能瓶颈我们可以引入缓存机制private final ConcurrentHashMapString, Expression expressionCache new ConcurrentHashMap(); private Expression getCachedExpression(String expr) { return expressionCache.computeIfAbsent(expr, parser::parseExpression); }4.2 上下文增强技巧扩展EvaluationContext注入更多实用对象context.setVariable(request, RequestContextHolder.getRequestAttributes()); context.setVariable(session, RequestContextHolder.getRequestAttributes().getSessionId());4.3 安全注意事项使用StandardEvaluationContext时需注意表达式注入风险对用户输入的表达式要做严格过滤。对于更敏感的场景可以使用SimpleEvaluationContextEvaluationContext context SimpleEvaluationContext.forReadOnlyDataBinding() .withInstanceMethods() .build();5. 测试策略确保权限系统可靠性的关键测试用例SpringBootTest public class DynamicAuthTests { Autowired private OrderController orderController; Test WithMockUser(username user1, roles MEMBER) public void testOwnerCheck() { Order testOrder new Order(); testOrder.setCreatedBy(user1); assertDoesNotThrow(() - orderController.updateOrder(1L, testOrder)); } Test WithMockUser(username user2, roles MEMBER) public void testNotOwner() { Order testOrder new Order(); testOrder.setCreatedBy(user1); assertThrows(AccessDeniedException.class, () - orderController.updateOrder(1L, testOrder)); } }这套方案在某电商后台系统上线后权限相关的代码量减少了40%同时满足了产品部门提出的17种动态权限需求。最复杂的权限规则只用了1行SpEL表达式就实现而传统方式需要编写数十行校验代码。

相关文章:

别再只会用@PreAuthorize了!手把手教你用SpringBoot AOP+自定义注解+SpEL打造更灵活的权限控制

超越PreAuthorize:用SpringBoot AOPSpEL构建动态权限控制体系 在后台管理系统开发中,权限控制是保障业务安全的核心环节。虽然Spring Security提供的PreAuthorize注解能够满足基础需求,但面对"仅工作日可访问"、"只能操作自己…...

TVA在显示面板制造与检测中的实践与挑战(4)

重磅预告:本专栏将独家连载新书《AI视觉技术:从入门到进阶》精华内容。本书是《AI视觉技术:从进阶到专家》的权威前导篇,特邀美国 TypeOne 公司首席科学家、斯坦福大学博士 Bohan 担任技术顾问。Bohan师从美国三院院士、“AI教母”…...

年薪百万不是梦!AI大模型十大高薪岗位全解析!AI大模型时代

在人工智能大模型的推动下,职场格局正在发生翻天覆地的变化。AI大模型不仅在技术领域引发革命,也为相关岗位的从业者带来了前所未有的薪资待遇。以下是AI大模型领域的热门岗位薪资盘点,带你详细了解这些高薪职位的职责要求和发展前景。1. AI系…...

告别盲调!手把手教你用ETAS ISOLAR配置AUTOSAR XCP模块(附A2L文件生成避坑指南)

告别盲调!手把手教你用ETAS ISOLAR配置AUTOSAR XCP模块(附A2L文件生成避坑指南) 在汽车电子控制单元(ECU)开发中,XCP协议作为测量与标定的黄金标准,其重要性不言而喻。但对于许多刚接触ETAS ISO…...

大模型算法工程师:AI黄金赛道!高薪+风口+大厂争抢,速来围观!

大模型算法工程师,是具备扎实算法基础,深度理解Transformer、预训练与微调等大模型核心技术,负责模型训练、优化、部署与迭代的技术核心岗位。当下大模型赛道持续爆发,企业对能落地的算法人才需求井喷,大模型算法工程师…...

ARM MMU-401调试寄存器与TLB访问机制详解

1. ARM MMU-401调试寄存器架构解析在ARM处理器架构中,内存管理单元(MMU)负责虚拟地址到物理地址的转换工作。MMU-401作为ARM CoreLink系列的重要组件,其调试寄存器设计提供了独特的TLB(Translation Lookaside Buffer)访问机制,这对系统开发人…...

YimMenu:GTA5最强防护与增强工具完整指南

YimMenu:GTA5最强防护与增强工具完整指南 【免费下载链接】YimMenu YimMenu, a GTA V menu protecting against a wide ranges of the public crashes and improving the overall experience. 项目地址: https://gitcode.com/GitHub_Trending/yi/YimMenu Yim…...

2026最权威的六大AI写作网站解析与推荐

Ai论文网站排名(开题报告、文献综述、降aigc率、降重综合对比) TOP1. 千笔AI TOP2. aipasspaper TOP3. 清北论文 TOP4. 豆包 TOP5. kimi TOP6. deepseek 当下各类AI写作工具不断涌现,然而多数都得付费订阅。本文着重关注真正能够免费使…...

2026届学术党必备的六大AI学术助手推荐

Ai论文网站排名(开题报告、文献综述、降aigc率、降重综合对比) TOP1. 千笔AI TOP2. aipasspaper TOP3. 清北论文 TOP4. 豆包 TOP5. kimi TOP6. deepseek 基于自然语言处理跟深度学习技术的智能创作工具,是AI写作软件。它能依照用户输入…...

2026届毕业生推荐的AI论文方案推荐榜单

Ai论文网站排名(开题报告、文献综述、降aigc率、降重综合对比) TOP1. 千笔AI TOP2. aipasspaper TOP3. 清北论文 TOP4. 豆包 TOP5. kimi TOP6. deepseek 当今学术写作范畴之内,一键生成论文的工具借由结构化模板以及智能填充技术&#…...

Umi-OCR:免费开源的离线文字识别工具终极指南

Umi-OCR:免费开源的离线文字识别工具终极指南 【免费下载链接】Umi-OCR OCR software, free and offline. 开源、免费的离线OCR软件。支持截屏/批量导入图片,PDF文档识别,排除水印/页眉页脚,扫描/生成二维码。内置多国语言库。 …...

【2026最新】Arduino IDE下载安装汉化保姆级教程(附安装包)

简介: Arduino IDE是全球最易用的开源单片机开发环境,专为初学者设计,支持Win/macOS/Linux全平台,免费开源。界面简洁、汉化便捷,配套教程丰富,兼容海量硬件与项目,助电子爱好者、学生和创客快…...

Claude Code 全攻略:命令大全 + 实战工作流(建议收藏)

Claude Code 全攻略:命令大全 实战工作流(建议收藏)1. Claude 常用命令查看版本:claude --version启动交互界面(当前目录):claude指定目录启动:claude /path/to/project升级到最新版…...

微信H5导航踩坑实录:绕过限制调用高德/百度地图,我用这招解决了(附完整代码)

微信H5导航功能深度优化:跨平台地图调用的实战解决方案 在移动互联网时代,H5页面作为轻量级应用载体,经常需要集成地图导航功能。然而,微信浏览器环境下的特殊限制让这一看似简单的需求变得异常复杂。本文将分享一套经过实战检验的…...

ArcGIS Server 切片服务发布实战:从ArcMap预处理到JavaScript加载的完整避坑指南

ArcGIS Server切片服务发布实战:从预处理到前端加载的全链路避坑指南 当遥感影像数据需要从本地TIF文件转变为可被全球访问的Web地图服务时,ArcGIS Server的切片服务发布流程往往成为GIS工程师的必经之路。这个看似标准化的技术路径中,却隐藏…...

抖音无水印下载终极指南:3分钟搞定批量下载,免费获取高清资源

抖音无水印下载终极指南:3分钟搞定批量下载,免费获取高清资源 【免费下载链接】douyin-downloader A practical Douyin downloader for both single-item and profile batch downloads, with progress display, retries, SQLite deduplication, and brow…...

ComfyUI-BiRefNet-ZHO:5分钟掌握AI图像视频抠图终极解决方案

ComfyUI-BiRefNet-ZHO:5分钟掌握AI图像视频抠图终极解决方案 【免费下载链接】ComfyUI-BiRefNet-ZHO Better version for BiRefNet in ComfyUI | Both img & video 项目地址: https://gitcode.com/gh_mirrors/co/ComfyUI-BiRefNet-ZHO 还在为繁琐的背景去…...

偏见检测代码总报错?R 4.3+ + tidymodels + fairness包协同失效真相,92%用户忽略的3个底层统计假设校验步骤

更多请点击: https://intelliparadigm.com 第一章:R 语言在大语言模型偏见检测中的统计方法 报错解决方法 在使用 R 语言对大语言模型(LLM)输出进行偏见量化分析时,常见报错包括 object bias_score not found、non-nu…...

产品经理必看:如何利用GB/T 4754-2017标准,搞定用户画像与市场细分?

产品经理实战指南:用GB/T 4754-2017标准重构用户画像方法论 当你在设计一款SaaS产品的注册表单时,"所属行业"这个下拉框是否总让用户纠结?当团队讨论"目标客群定位"时,各部门对"金融科技客户"的定义…...

PHP支付系统国密改造实录:从OpenSSL到GMSSL的7大断点排查与3小时热切换方案

更多请点击: https://intelliparadigm.com 第一章:PHP支付系统国密改造的背景与合规要求 随着《密码法》正式施行及《金融行业信息系统商用密码应用基本要求》(JR/T 0092—2021)等监管文件落地,面向金融级业务的PHP支…...

如何用3分钟从视频中智能提取PPT:告别手动截图的终极指南

如何用3分钟从视频中智能提取PPT:告别手动截图的终极指南 【免费下载链接】extract-video-ppt extract the ppt in the video 项目地址: https://gitcode.com/gh_mirrors/ex/extract-video-ppt 你是否曾花费数小时从教学视频或会议录像中手动截图保存PPT内容…...

SAP ABAP ALV表格里,如何给自定义字段加上F4搜索帮助?(附完整代码示例)

SAP ABAP ALV表格自定义字段F4搜索帮助实战指南 在SAP ABAP开发中,ALV(ABAP List Viewer)表格是最常用的数据展示控件之一。当我们需要在ALV表格中实现数据录入功能时,F4搜索帮助(输入帮助)能够显著提升用户…...

中国数字资产安全新纪元:Ledger 官方直营时代开启

中国数字资产安全新纪元:Ledger 官方直营时代开启 【核心摘要】 2026 年,中国数字资产安全领域迎来里程碑式变革——法国 Ledger 正式确立大中华区直营服务体系。通过京东(JD.com)及微信生态构建的官方授权链路,彻底解…...

RimSort终极指南:如何轻松管理《环世界》模组,告别加载冲突烦恼

RimSort终极指南:如何轻松管理《环世界》模组,告别加载冲突烦恼 【免费下载链接】RimSort RimSort is an open source mod manager for the video game RimWorld. There is support for Linux, Mac, and Windows, built from the ground up to be a reli…...

别再只用一个ChatGPT了!试试Poe这个AI聊天机器人聚合平台,一次体验ChatGPT、Claude、Sage和Dragonfly

解锁AI协作新维度:Poe平台多模型智能工作流实战指南 当ChatGPT成为日常生产力工具的代名词,许多深度用户开始意识到:不同AI模型其实各有所长。就像专业摄影师不会只用一支镜头完成所有拍摄,真正的效率追求者需要学会调用最适合当前…...

K8S证书管理避坑指南:除了kubeadm certs renew,你还需要知道这些备份和验证技巧

K8S证书管理避坑指南:从备份到验证的全流程安全策略 当Kubernetes集群的证书突然失效时,整个集群可能瞬间陷入瘫痪——API调用失败、kubectl命令无法执行、核心组件间通信中断。这不是危言耸听,而是每个运维工程师都可能面临的真实噩梦。本文…...

【新手攻略】2026年OpenClaw/Hermes Agent京东云6分钟快速安装指南

【新手攻略】2026年OpenClaw/Hermes Agent京东云6分钟快速安装指南。OpenClaw和Hermes Agent是什么?OpenClaw和Hermes Agent怎么部署?如何部署OpenClaw/Hermes Agent?2026年还在为部署OpenClaw和Hermes Agent到处找教程踩坑吗?别再…...

别再死记硬背了!用Flink SQL窗口函数搞定实时订单统计(附Kafka数据源配置)

实时电商订单分析的Flink SQL窗口函数实战指南 电商平台每天产生海量订单数据,如何实时分析这些数据成为技术团队面临的挑战。本文将深入探讨如何利用Flink SQL的窗口函数实现电商订单的实时统计分析,从基础概念到实战应用,帮助开发者快速掌握…...

FPGA防变砖指南:巧用ICAP原语和Fallback地址,给你的产品加一道“安全锁”

FPGA双镜像容错系统设计:从ICAP原理到工业级安全升级方案 当你的FPGA设备在偏远地区的变电站运行时,突然遭遇断电;当医疗设备的固件升级因网络波动导致数据包丢失;当自动驾驶系统的现场更新被意外中断——这些场景下,传…...

【PHP Swoole × LLM长连接终极方案】:20年架构师亲授插件一键部署、零配置接入与百万级并发实测数据

更多请点击: https://intelliparadigm.com 第一章:PHP Swoole LLM长连接终极方案插件概览 在构建高并发、低延迟的 AI 服务网关时,传统 PHP-FPM 架构难以承载 LLM(大语言模型)推理会话所需的双向长连接与实时流式响…...