Spring Security方法级安全控制@PreAuthorize注解的灵活运用小结

本文主要是介绍Spring Security方法级安全控制@PreAuthorize注解的灵活运用小结,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

《SpringSecurity方法级安全控制@PreAuthorize注解的灵活运用小结》本文将带着大家讲解@PreAuthorize注解的核心原理、SpEL表达式机制,并通过的示例代码演示如...

1. 前言

在实js际项目中,安全控制不编程仅体现在 URL 拦截层面,方法级安全控制也越来越受到重视。Spring Security 提供了多种方式实现方法级安全,Spring Security 通过方法注解体系,这种细粒度控制使得我们能够在方法调用前、调用后,甚至返回值处理阶段实施安全检查,真正成为开发者保护服务接口的重要手段

相信小伙伴通过前面章节的学习,发现了博主在方法上进行角色和菜单资源验证的时候使用的一个注解:@PreAuthorize,那么本章节博主将带着大家剖析 @PreAuthorize 注解的核心原理、SpEL 表达式机制,并通过的示例代码演示如何在实际项目中灵活运用该注解实现细粒度的权限控制。

2. @PreAuthorize 注解简介

@PreAuthorize 注解可以在方法执行前对传入的参数、当前用户信息、认证状态等进行校验,从而决定是否允许方法执行。常见使用场景包括:

  • 限制某个接口或方法只允许特定角色访问;
  • 根据方法参数和认证信息动态判断权限;
  • 调用自定义的权限判断逻辑(例如上一个章节中结合自定义 PermissionEvaLuator);
  • 限制某个接口或方法只允许特定角色访问;
  • 根据方法参数和认证信息动态判断权限;
  • 调用自定义的权限判断逻辑(例如上一个章节中结合自定义 PermissionEvaluator);

Spring Security 内部通过 AOP 拦截被 @PreAuthorize 修饰的方法,并利用 Spring Expression Language(SpEL)对注解中定义的表达式进行求值。只有当表达式求值结果为 true 时,方法才会执行,否则会抛出拒绝访问异常。

3. @PreAuthorize 核心原理解析

Spring Security 开启方法级安全控制实际上非常简单,只需要在 @Cjsonfiguration 配置类中添加 @EnableMethodSecurity

@Configuration
//开启方法级的安全控制
@EnableMethodSecurity
public class AbacSecurityConfig {
	//....
}

方法授权可以分为方法前授权方法后授权的组合,看下面的例子

@Service
public class MyCustomerService {
    @PreAuthorize("hasAuthority('permission:read')")
    @PostAuthorize("returnObject.owner == authentication.name")
    public Customer readCustomer(String id) { ... }
}

当方法安全性被激活时,对 MyCustomerService#readCustomer 的调用流程如下(官方流程图):

Spring Security方法级安全控制@PreAuthorize注解的灵活运用小结

流程解析

Spring AOP 为 readCustomer 调用其代理方法。它调用与AuthorizationManagerBeforeMethodInterceptor切入点匹配的@PreAuthorize
拦截器调用 PreAuthorizeAuthorizationManager#check
授权python管理器使用 MethodSecurityExpressionHandler 解析注释的 SpEL表达式,并从包含EvaluationContext和MethodSecurityExpressionRoot的Supplier构造对应的MethodInvocation。
拦截器使用此上下文来评估表达式,它从Authentication读取Supplier,并检查其权限集合中是否有permission:read
如果评估通过,那么Spring AOP继续调用该方法
如果不通过,拦截器发布一个AuthorizationDeniedEvent并抛出一个AccessDeniedException,ExceptionTranslationFilter捕获并向响应返回一个403状态码
方法返回后,Spring AOP 调用与切入点匹配AuthorizationManagerAfterMethodInterceptor的,操作与上面相同,但是@PostAuthorizePostAuthorizeAuthorizationManager
如果评估通过(在这种情况下,返回值属于登录用户),则处理继续正常进行
如果不通过,拦截器将发布一个AuthorizationDeniedEvent并抛出一个AccessDeniedException,然后捕获ExceptionTranslationFilter并向响应返回 403 状态代码

拦截与表达式求值

从上述官方介绍的工作流程来看,我们可以简单总结为:

Spring Security 在启用方法级安全时,会在应用上下文中配置一个 MethodSecurityInte编程rceptor(基于 AOP 实现)。当被 @PreAuthorize 修饰的方法被调用时:

  • 拦截器捕获方法调用,并构造 EvaluationContext,上下文中包含认证信息、方法参数等数据
  • 使用 MethodSecurityExpressionHandler 将注解中的 SpEL 表达式求值,判断是否满足访问条件
  • 如果表达式结果为 false,则抛出 AccessDeniedException 否则放行执行方法

Spring Security方法级安全控制@PreAuthorize注解的灵活运用小结

SpEL 表达式

@PreAuthorize 注解的值是一个 SpEL 表达式,可以引用以下内置变量:

  • authentication:当前用户的认证对象。
  • principal:当前认证用户的主体信息(通常为 UserDetails 对象)。
  • #root:表达式根对象。
  • 方法参数:可以通过 #paramName 或 #p0 访问方法参数。

如下代码

@PreAuthorize("hasRole('ADMIN') and #id > 10")
public void deleteUser(Long id) { ... }

表示只有当前用户拥有 ADMIN 角色且方法参数 id 大于 10 时,才能执行该方法。

自定义扩展

通过自定义 MethodSecurityExpressionHandler 和 PermissionEvaluator,可以扩展 @PreAuthorize 表达式功能。具体可以查阅上个章节ABAC属性权限模型实战开发

注解应用实战

下面通过一些简单示例,演示如何配置 Spring Security 方法级安全

❶ 基础权限校验

@PreAuthorize("hasRole('ADMIN')")
public void deleteResource(Long resourceId){
    // 方法实现
}
@PreAuthorize("hasAuthority('RESOURCE_APPROVE')")
public void approveRequest(Request request){
    // 审批逻辑
}

❷ 参数级权限控制

// 校验创建者匹配
@PreAuthorize("#article.createdBy == authentication.name")
public void updateArticle(Article article){
    // 更新操作
}
// 参数过滤示例
@PreAuthorize("@permissionChecker.hasAccess(#userId, 'EDIT')")
public void editUserProfile(Long userId, Profile profile){
    // 编辑逻辑
}

❸ 动态业务规则集成

如没有了解的小伙伴,建议查阅博主上一章节内容(这里仅演示如何配置@PreAuthorize):
最新Spring Security实战教程(六)最新Spring Security实战教程(六)基于数据库的ABAC属性权限模型实战开发

public class DocumentPermissionEvaluator {
    public boolean checkAccess(Long docId, String permission) {
        // 自定义文档权限校验逻辑
    }
}
// 在SpEL中调用自定义评估器
@PreAuthorize("@documentPermissionEvaluator.checkAccess(#docId, 'WRITE')")
public void updateDocument(Long docId, String content){
    // 文档更新
}

❹ 复合条件表达式

// 组合多个条件
@PreAuthorize("hasRole('ADMIN') or (#user.department == authentication.user.department and hasAuthority('DEPT_ADMIN'))")
public void manageUser(User user){
    // 用户管理逻辑
}

❺ 返回值后校验

@PostAuthorize("returnObject.owner == authentication.name")
public Document getConfidentialDocument(Long id){
    // 获取文档逻辑
}

❻ 参数预处理

@PreFilter("filterObject.owner == authentication.name")
public void BATchProcess(List<Document> documents){
    // 仅处理当前用户拥有的文档
}

结语

通过本章节方法级安全控制的介绍,相信大家已经能通过灵活运用表达式语言和自定义扩展,让我们可以在保证系统安全性的同时,维持代码的优雅与可维护性!希望这章节文章对你在 Spring Security 方法级安全控制的实践中提供帮助和启发!

到此这篇关于Spring Security方法级安全控制@PreAuthorize注解的灵活运用小结的文章就介绍到这了,更多相关Spring Security @PreAuthorize注解内容请搜索China编程(www.chinasem.cn)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程China编程(www.chinasem.cn)!

这篇关于Spring Security方法级安全控制@PreAuthorize注解的灵活运用小结的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1154137

相关文章

Java中流式并行操作parallelStream的原理和使用方法

《Java中流式并行操作parallelStream的原理和使用方法》本文详细介绍了Java中的并行流(parallelStream)的原理、正确使用方法以及在实际业务中的应用案例,并指出在使用并行流... 目录Java中流式并行操作parallelStream0. 问题的产生1. 什么是parallelS

MySQL数据库双机热备的配置方法详解

《MySQL数据库双机热备的配置方法详解》在企业级应用中,数据库的高可用性和数据的安全性是至关重要的,MySQL作为最流行的开源关系型数据库管理系统之一,提供了多种方式来实现高可用性,其中双机热备(M... 目录1. 环境准备1.1 安装mysql1.2 配置MySQL1.2.1 主服务器配置1.2.2 从

Java中Redisson 的原理深度解析

《Java中Redisson的原理深度解析》Redisson是一个高性能的Redis客户端,它通过将Redis数据结构映射为Java对象和分布式对象,实现了在Java应用中方便地使用Redis,本文... 目录前言一、核心设计理念二、核心架构与通信层1. 基于 Netty 的异步非阻塞通信2. 编解码器三、

SpringBoot基于注解实现数据库字段回填的完整方案

《SpringBoot基于注解实现数据库字段回填的完整方案》这篇文章主要为大家详细介绍了SpringBoot如何基于注解实现数据库字段回填的相关方法,文中的示例代码讲解详细,感兴趣的小伙伴可以了解... 目录数据库表pom.XMLRelationFieldRelationFieldMapping基础的一些代

一篇文章彻底搞懂macOS如何决定java环境

《一篇文章彻底搞懂macOS如何决定java环境》MacOS作为一个功能强大的操作系统,为开发者提供了丰富的开发工具和框架,下面:本文主要介绍macOS如何决定java环境的相关资料,文中通过代码... 目录方法一:使用 which命令方法二:使用 Java_home工具(Apple 官方推荐)那问题来了,

Java HashMap的底层实现原理深度解析

《JavaHashMap的底层实现原理深度解析》HashMap基于数组+链表+红黑树结构,通过哈希算法和扩容机制优化性能,负载因子与树化阈值平衡效率,是Java开发必备的高效数据结构,本文给大家介绍... 目录一、概述:HashMap的宏观结构二、核心数据结构解析1. 数组(桶数组)2. 链表节点(Node

Java AOP面向切面编程的概念和实现方式

《JavaAOP面向切面编程的概念和实现方式》AOP是面向切面编程,通过动态代理将横切关注点(如日志、事务)与核心业务逻辑分离,提升代码复用性和可维护性,本文给大家介绍JavaAOP面向切面编程的概... 目录一、AOP 是什么?二、AOP 的核心概念与实现方式核心概念实现方式三、Spring AOP 的关

详解SpringBoot+Ehcache使用示例

《详解SpringBoot+Ehcache使用示例》本文介绍了SpringBoot中配置Ehcache、自定义get/set方式,并实际使用缓存的过程,文中通过示例代码介绍的非常详细,对大家的学习或者... 目录摘要概念内存与磁盘持久化存储:配置灵活性:编码示例引入依赖:配置ehcache.XML文件:配置

Java 虚拟线程的创建与使用深度解析

《Java虚拟线程的创建与使用深度解析》虚拟线程是Java19中以预览特性形式引入,Java21起正式发布的轻量级线程,本文给大家介绍Java虚拟线程的创建与使用,感兴趣的朋友一起看看吧... 目录一、虚拟线程简介1.1 什么是虚拟线程?1.2 为什么需要虚拟线程?二、虚拟线程与平台线程对比代码对比示例:三

Python版本信息获取方法详解与实战

《Python版本信息获取方法详解与实战》在Python开发中,获取Python版本号是调试、兼容性检查和版本控制的重要基础操作,本文详细介绍了如何使用sys和platform模块获取Python的主... 目录1. python版本号获取基础2. 使用sys模块获取版本信息2.1 sys模块概述2.1.1