【问题标题】:configure(HttpSecurity http) and configure(AuthenticationManagerBuilder) get ignored with certain annotations in WebSecurityConfigurerAdapter配置(HttpSecurity http)和配置(AuthenticationManagerBuilder)被WebSecurityConfigurerAdapter中的某些注释忽略
【发布时间】:2021-05-31 12:37:40
【问题描述】:

我正在尝试保护具有不同用户角色的 Spring 应用程序。虽然 Authentication 部分已设置并且可以完美运行,但我在 Authorization 部分的实施过程中意识到,使用某些注释,SecurityConfiguration extends WebSecurityConfigurerAdapter class 中的两个覆盖方法之一会被忽略。

public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

  @Autowired
  private WebApplicationContext applicationContext;
  private CredentialsService userDetailsService;

  @Autowired
  private DataSource dataSource;

  @PostConstruct
  public void completeSetup() {
    userDetailsService =   applicationContext.getBean(CredentialsService.class);
  }

  @Override
  protected void configure(final HttpSecurity http) throws Exception {
    http.authorizeRequests()
            .antMatchers("/login")
            .permitAll()
            .and()
            .formLogin()
            .permitAll()
            .and()

            .httpBasic()
            .disable()

            .authorizeRequests()
            .antMatchers("/admin", "/admin/**")
            .hasRole("ADMIN")
            .and()

            .authorizeRequests()
            .antMatchers("/employee", "/employee/**")
            .hasRole("EMPLOYEE")
            .and()

            .authorizeRequests()
            .antMatchers("/customer", "/customer/**")
            .hasRole("CUSTOMER");
  }

  @Override
  protected void configure(final AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(userDetailsService)
            .passwordEncoder(encoder())
            .and()
            .authenticationProvider(authenticationProvider())
            .jdbcAuthentication()
            .dataSource(dataSource);
  }


  @Bean
  public DaoAuthenticationProvider authenticationProvider() {
    final DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
    authProvider.setUserDetailsService(userDetailsService);
    authProvider.setPasswordEncoder(encoder());
    return authProvider;
  }

  @Bean
  public PasswordEncoder encoder() {
    return new BCryptPasswordEncoder(12);
  }
}

现在的问题是,这个类对我的用户进行身份验证,但有一个主要缺点:

configure(final HttpSecurity http) throws Exception {

被完全忽略。

但另一方面,如果我在班级顶部添加 @Configuration 注释,则

protected void configure(final AuthenticationManagerBuilder auth) throws Exception {

被完全忽略,因此将破坏授权,因为它无法在我的自定义 UserDetailsService 实现上调用 getUsername() 和 getPassword。

如您所见,我使用 DaoAuthenticationProvider 实例作为 authenticationProvider,因为我的应用程序从外部数据库检索用户/密码。

我现在采用的快速修复方法是在我的主类中添加以下方法

@EnableGlobalMethodSecurity(
        securedEnabled = true,
        jsr250Enabled = true,
        prePostEnabled = true
)

以及在我的受限控制器上使用@Secured 注释。这行得通,但我想了解为什么 Spring 会有如此奇怪的行为,以及我可以采取什么步骤来解决这些问题。

【问题讨论】:

    标签: spring authentication spring-security


    【解决方案1】:

    由于您要为用户分配角色,请使用语法

    .antMatchers("/admin", "/admin/**")
    .hasRole("ADMIN")
    

    .antMatchers("/admin", "/admin/**")
    .hasAuthority("ROLE_ADMIN")
    

    角色只是存储为带有“ROLE_”前缀的权限。
    所以角色“ADMIN”等价于权限“ROLE_ADMIN”。

    编辑 1

    您还可以简化配置以明确所有内容的来源。

    由于你UserDetailsService (CredentialsService) 已经是一个bean,它会被Spring Security 自动拾取。

    @Configuration
    public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
    
      // The password encoder should be a bean
      @Bean
      public PasswordEncoder encoder() {
        return new BCryptPasswordEncoder(12);
      }
    
      @Override
      protected void configure(final HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/login")
                .permitAll()
                .and()
                .formLogin()
                .permitAll()
                .and()
    
                .authorizeRequests()
                .antMatchers("/admin", "/admin/**")
                .hasRole("ADMIN")
                .and()
    
                .authorizeRequests()
                .antMatchers("/manager", "/manager/**")
                .hasRole("MANAGER")
                .and()
    
                .authorizeRequests()
                .antMatchers("/customer", "/customer/**")
                .hasRole("CUSTOMER");
      }
    
    }
    

    【讨论】:

    • 谢谢Eleftheria,我试过了,可惜不行,用户仍然可以访问受限控制器。
    • @WebStormer 我已将我的答案更新为您可以尝试的简化配置
    • Eleftheria Stein-Kousathana 我找到了问题所在,我重新编写了问题,请随意看看!
    猜你喜欢
    • 1970-01-01
    • 2021-04-23
    • 2020-03-25
    • 1970-01-01
    • 2017-09-21
    • 2016-09-13
    • 1970-01-01
    • 2016-09-14
    • 1970-01-01
    相关资源
    最近更新 更多