• SpringSecurity系列——访问控制之基于方法的控制day6-3(源于官网5.7.2版本)


    方法安全表达式

    方法安全性比简单的允许或拒绝规则要复杂一些。 Spring Security 3.0 引入了一些新的注解,以便全面支持表达式的使用。

    EnableMethodSecurity(启用方法安全)

    在 Spring Security 5.6 中,我们可以在任何 @Configuration 实例上使用 @EnableMethodSecurity 注解启用基于注解的安全性。

    这以多种方式改进了@EnableGlobalMethodSecurity。 @EnableMethodSecurity:

    1. 使用简化的 AuthorizationManager API,而不是元数据源、配置属性、决策管理器和选民。 这简化了重用和定制。
    2. 支持直接基于 bean 的配置,而不是需要扩展 GlobalMethodSecurityConfiguration 来自定义 bean
    3. 使用原生 Spring AOP 构建,去除抽象并允许您使用 Spring AOP 构建块进行自定义
    4. 检查冲突的注释以确保明确的安全配置
    5. 符合 JSR-250
    6. 默认启用@PreAuthorize、@PostAuthorize、@PreFilter 和@PostFilter

    关于@Pre 和 @Post 注释

    有四个注释支持表达式属性,以允许调用前和调用后的授权检查,还支持过滤提交的集合参数或返回值。 他们是 @PreAuthorize, @PreFilter, @PostAuthorize和 @PostFilter

    关于@PreAuthorize

    在方法执行前进行判断
    最明显有用的注释是 @PreAuthorize它决定了是否可以实际调用方法

    @PreAuthorize("hasRole('USER')")
    public void create(Contact contact);
    
    • 1
    • 2

    这意味着只有角色为“ROLE_USER”的用户才允许访问。 显然,使用传统配置和所需角色的简单配置属性可以轻松实现相同的目标

    @PreAuthorize实例

    当然在注解中也可以对各种权限判断策略进行判断,使用这个注解的形式就不用进行配置了
    在这里插入图片描述

    1.在SpringSecurity上开启方法安全

    @EnableMethodSecurity
    @EnableWebSecurity
    @Configuration
    public class SpringSecurityConfig {}
    
    • 1
    • 2
    • 3
    • 4

    2.在需要权限控制方法上加注解

    	@PreAuthorize("hasAuthority('ROLE_admin')")
        @GetMapping("/test7")
        public String tt6() {
            return "/test7....";
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    关于@PostAuthorize

    @PostAuthorize注解其实使用的并不多,因为是在方法执行结束之后对于权限进行判断

    Customizing Authorization(自定义授权)

    Spring Security 的@PreAuthorize、@PostAuthorize、@PreFilter 和@PostFilter 提供了丰富的基于表达式的支持。

    如果您需要自定义处理表达式的方式,您可以公开一个自定义 MethodSecurityExpressionHandler,就像这样

    自定义 MethodSecurityExpressionHandler

    @Bean
    static MethodSecurityExpressionHandler methodSecurityExpressionHandler() {
    	DefaultMethodSecurityExpressionHandler handler = new DefaultMethodSecurityExpressionHandler();
    	handler.setTrustResolver(myCustomTrustResolver);
    	return handler;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    我们使用静态方法暴露 MethodSecurityExpressionHandler 以确保 Spring 在初始化 Spring Security 的方法安全 @Configuration 类之前发布它

    此外,对于基于角色的授权,Spring Security 添加了一个默认的 ROLE_ 前缀,用于评估像 hasRole 这样的表达式。

    您可以通过公开 GrantedAuthorityDefaults bean 来配置授权规则以使用不同的前缀,如下所示

    示例 :自定义 MethodSecurityExpressionHandler

    @Bean
    static GrantedAuthorityDefaults grantedAuthorityDefaults() {
    	return new GrantedAuthorityDefaults("MYPREFIX_");
    }
    
    • 1
    • 2
    • 3
    • 4

    我们使用静态方法暴露 GrantedAuthorityDefaults 以确保 Spring 在初始化 Spring Security 的方法 security @Configuration 类之前发布它

    Custom Authorization Managers(自定义授权管理器)

    方法授权是方法前授权和方法后授权的组合。

    方法前授权是在调用方法之前执行的。 如果该授权拒绝访问,则不调用该方法,并抛出 AccessDeniedException 方法后授权在调用该方法之后,但在该方法返回给调用者之前执行。 如果该授权拒绝访问,则不返回该值,并抛出 AccessDeniedException

    要重新创建默认情况下添加 @EnableMethodSecurity 所做的事情,您将发布以下配置

    完整的前置后置方法安全配置

    @EnableMethodSecurity(prePostEnabled = false)
    class MethodSecurityConfig {
    	@Bean
    	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    	Advisor preFilterAuthorizationMethodInterceptor() {
    		return new PreFilterAuthorizationMethodInterceptor();
    	}
    
    	@Bean
    	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    	Advisor preAuthorizeAuthorizationMethodInterceptor() {
    		return AuthorizationManagerBeforeMethodInterceptor.preAuthorize();
    	}
    
    	@Bean
    	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    	Advisor postAuthorizeAuthorizationMethodInterceptor() {
    		return AuthorizationManagerAfterMethodInterceptor.postAuthorize();
    	}
    
    	@Bean
    	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    	Advisor postFilterAuthorizationMethodInterceptor() {
    		return new PostFilterAuthorizationMethodInterceptor();
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    请注意,Spring Security 的方法安全性是使用 Spring AOP 构建的。 因此,拦截器是根据指定的顺序调用的。 这可以通过在拦截器实例上调用 setOrder 来定制,如下所示

    发布自定义顾问

    @Bean
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    Advisor postFilterAuthorizationMethodInterceptor() {
    	PostFilterAuthorizationMethodInterceptor interceptor = new PostFilterAuthorizationMethodInterceptor();
    	interceptor.setOrder(AuthorizationInterceptorOrders.POST_AUTHORIZE.getOrder() - 1);
    	return interceptor;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    仅@PreAuthorize 配置

    您可能只想在应用程序中支持 @PreAuthorize,在这种情况下,您可以执行以下操作:

    @EnableMethodSecurity(prePostEnabled = false)
    class MethodSecurityConfig {
    	@Bean
    	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    	Advisor preAuthorize() {
    		return AuthorizationManagerBeforeMethodInterceptor.preAuthorize();
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    或者,您可能有一个要添加到列表中的自定义方法前 AuthorizationManager。

    在这种情况下,您需要告诉 Spring Security AuthorizationManager 以及您的授权管理器适用于哪些方法和类。

    因此,您可以配置 Spring Security 以在 @PreAuthorize 和 @PostAuthorize 之间调用您的 AuthorizationManager,如下所示:

    建议之前的自定义

    @EnableMethodSecurity
    class MethodSecurityConfig {
    	@Bean
    	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    	public Advisor customAuthorize() {
    		JdkRegexpMethodPointcut pattern = new JdkRegexpMethodPointcut();
    		pattern.setPattern("org.mycompany.myapp.service.*");
    		AuthorizationManager<MethodInvocation> rule = AuthorityAuthorizationManager.isAuthenticated();
    		AuthorizationManagerBeforeMethodInterceptor interceptor = new AuthorizationManagerBeforeMethodInterceptor(pattern, rule);
    		interceptor.setOrder(AuthorizationInterceptorsOrder.PRE_AUTHORIZE_ADVISOR_ORDER.getOrder() + 1);
    		return interceptor;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    您可以使用 AuthorizationInterceptorsOrder 中指定的顺序常量将拦截器放置在 Spring Security 方法拦截器之间。
    对于后方法授权也可以这样做。 方法后授权通常涉及分析返回值以验证访问。

    例如,您可能有一个方法可以确认请求的帐户实际上属于登录用户,如下所示:

    @PostAuthorize 示例

    @EnableMethodSecurity
    class MethodSecurityConfig {
    	@Bean
    	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    	public Advisor customAuthorize(AuthorizationManager<MethodInvocationResult> rules) {
    		AnnotationMethodMatcher pattern = new AnnotationMethodMatcher(MySecurityAnnotation.class);
    		AuthorizationManagerAfterMethodInterceptor interceptor = new AuthorizationManagerAfterMethodInterceptor(pattern, rules);
    		interceptor.setOrder(AuthorizationInterceptorsOrder.POST_AUTHORIZE_ADVISOR_ORDER.getOrder() + 1);
    		return interceptor;
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
  • 相关阅读:
    什么是对象存储COS?它又有哪些优势?
    java从键盘输入Scanner
    QT移植腾讯云C-SDK结合实现OTA更新
    pandas merge 和 concat
    【无标题】
    算法日记-02完全背包和多重背包问题总结
    回调封装ajax
    Go 运算符
    SpringBoot不同环境加载不同配置文件(dev,sit,uat)
    web前端期末大作业:基于HTML+CSS+JS外卖服务平台10页 带购物车 (web课程设计与实现)
  • 原文地址:https://blog.csdn.net/qq_51553982/article/details/126006605