【问题标题】:Roles hierarchy not working after upgrading to spring security 6升级到 spring security 6 后角色层次结构不起作用
【发布时间】:2023-02-24 05:14:46
【问题描述】:

我正在从 spring boot 2.7.x 升级到 3.0.0。按照官方文档中的建议进行更改后,我发现我的角色层次结构没有得到尊重。

我按照 AccessDecisionVoter Deprecated with Spring Security 6.x 中的建议将 expressionHandler() 添加到我的代码中,但它不起作用。

任何想法我错过了什么?

@Configuration
@EnableWebSecurity
public class WebSecurityConfig {

  @Bean
  public SecurityFilterChain configure(
      HttpSecurity http,
      RequestHeaderAuthenticationFilter headerAuthenticationFilter) throws Exception {
    
    HttpStatusEntryPoint authenticationEntryPoint = 
        new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED);
    
    http
        .addFilterAfter(headerAuthenticationFilter, RequestHeaderAuthenticationFilter.class)
        .authorizeHttpRequests(auth -> auth
          .requestMatchers("/actuator/**", "/", "/webjars/**").permitAll()
          .requestMatchers(HttpMethod.POST).hasRole("SUPERUSER")
          .requestMatchers(HttpMethod.GET).hasRole("USER"))
        .sessionManagement(session -> session
          .sessionCreationPolicy(SessionCreationPolicy.STATELESS))
        .exceptionHandling(ex -> ex
          .authenticationEntryPoint(authenticationEntryPoint)
          .accessDeniedHandler(accessDeniedHandler()))
        .csrf(customizer -> customizer.disable());

    return http.build();
  }

  @Bean
  public RequestHeaderAuthenticationFilter headerAuthenticationFilter(
      ...
  }

  @Bean
  public RoleHierarchy roleHierarchy() {
    RoleHierarchyImpl r = new RoleHierarchyImpl();
    r.setHierarchy("ROLE_SUPERUSER > ROLE_USER");
    return r;
  }

  @Bean
  public DefaultWebSecurityExpressionHandler expressionHandler() {
    DefaultWebSecurityExpressionHandler expressionHandler = new DefaultWebSecurityExpressionHandler();
    expressionHandler.setRoleHierarchy(roleHierarchy());
    return expressionHandler;
  }

【问题讨论】:

    标签: spring security configuration upgrade


    【解决方案1】:

    AuthorityAuthorizationManager 未作为 bean 公开。事实上,它是一个带有私有构造函数的最终类。因此,为了使用我的角色层次结构,我需要手动创建 AuthorityAuthorizationManager。

    这适用于 spring boot 3.0.0 和 spring security 6.0.0

      @Bean
      public SecurityFilterChain configure(
          HttpSecurity http,
          RequestHeaderAuthenticationFilter headerAuthenticationFilter) throws Exception {
    
        var auth1 = AuthorityAuthorizationManager.<RequestAuthorizationContext>hasRole("USER");
        auth1.setRoleHierarchy(roleHierarchy());
        
        http
            .authorizeHttpRequests(auth -> auth
              .requestMatchers(HttpMethod.GET).access(auth1)
            );
        return http.build();
      }
    
     @Bean
      public RoleHierarchy roleHierarchy() {
        RoleHierarchyImpl r = new RoleHierarchyImpl();
        r.setHierarchy("ROLE_SUPERUSER > ROLE_USER");
        return r;
      }
    

    【讨论】:

      【解决方案2】:

      我发现最好的方法是像AbstractUserDetailsAuthenticationProvider 那样调用GrantedAuthoritiesMapper#mapAuthorities。 不幸的是PreAuthenticatedAuthenticationProvider 没有以同样的方式调用它,所以你必须自己做。

      这将使它可以在任何地方工作,包括方法安全和 HttpSecurity 以外的其他地方。鉴于大多数身份验证提供商都在这样做,这可能是正确的方法。它还将避免根据每个请求扩展层次结构。

        @Bean
        public GrantedAuthoritiesMapper grantedAuthoritiesMapper(RoleHierarchy roleHierarchy) {
            return new RoleHierarchyAuthoritiesMapper(roleHierarchy);
        }
      
        @Bean
        public RequestHeaderAuthenticationFilter headerAuthenticationFilter(GrantedAuthoritiesMapper mapper) {
            //...
            filter.setAuthenticationDetailsSource(context -> {
                //...
                return new PreAuthenticatedGranteduthoritiesWebAuthenticationDetails(context, mapper.mapAuthorities(authorities));
            });
            return filter;
        }
      
      

      【讨论】:

        猜你喜欢
        • 2012-10-19
        • 2016-01-03
        • 2012-12-01
        • 2013-10-31
        • 2019-12-12
        • 2019-06-21
        • 2011-11-21
        • 2023-02-04
        • 2011-11-03
        相关资源
        最近更新 更多