【问题标题】:SpringSecurity BasicAuthenticationFilter with custom AuthenticationManager带有自定义 AuthenticationManager 的 SpringSecurity BasicAuthenticationFilter
【发布时间】:2019-05-02 20:40:24
【问题描述】:

对于 BasicAuthenticationFilter,我正在尝试注入我自己的 AuthenticationManager。 但是当我调试 Startup 时,我总是发现 Class BasicAuthenticationFilter.java 没有使用我的 AuthenticationManager。

如何将其传递到 BasicAuthenticationFilter 中?

我正在使用 SpringBoot 2.1.0 和 Spring-Security-Oauth2 2.0.1

AuthorizationConfiguration.java

@Configuration
@EnableAuthorizationServer
public class AuthorizationConfiguration extends 
AuthorizationServerConfigurerAdapter {

@Autowired
private AuthenticationManager authenticationManager;

@Autowired
@Qualifier("passwordEncoder")
private PasswordEncoder passwordEncoder;

@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
    System.out.println(passwordEncoder.encode("SECRET"));
    clients
    .inMemory()
    .withClient("clientapp")
    .authorizedGrantTypes("client_credentials")
    .authorities("USER")
    .scopes("read", "write")
    .secret(passwordEncoder.encode("SECRET"));

}

@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
    security.tokenKeyAccess("permitAll()");
}

@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
    endpoints.authenticationManager(authenticationManager);
}
}

WebSecurityConfiguration.java

@Configuration
@EnableWebSecurity
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter{

@Override
@Bean(name = BeanIds.AUTHENTICATION_MANAGER)
@Primary
public AuthenticationManager authenticationManagerBean() throws Exception {
    return super.authenticationManager();
}


@Bean
public PasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder(16); 
}

@Override
public void configure(WebSecurity web) throws Exception {
    web.ignoring()
    .antMatchers(ResourceConfiguration.TEST_PATHS);
}

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    DaoAuthenticationProvider daoAuth = new DaoAuthenticationProvider();
    daoAuth.setPasswordEncoder(passwordEncoder());
    auth.authenticationProvider(daoAuth);
}

感谢您的帮助。

【问题讨论】:

    标签: java spring spring-security oauth spring-security-oauth2


    【解决方案1】:

    问题是我在 build.gradle 中使用了错误的包

    为了解决这个问题,我添加了以下包:

    build.gradle

    implementation("org.springframework.security.oauth.boot:spring-security-oauth2-autoconfigure:${springBootVersion}")
    

    【讨论】:

      【解决方案2】:

      使用您给定的配置,您实际上将获得两个BasicAuthenticationFilter 实例。两者都应该得到你的AuthenticationManager 就好了。但是,对于其中一个,它是父 AuthenticationManager,这意味着您还应该在调试器中检查 authenticationManager.parent 属性。

      不过,您的AuthenticationManager 可能存在一些问题。

      Spring Security OAuth 将创建两个过滤器链(随后是两个BasicAuthenticationFilters,两个AuthenticationManagers);一个用于 OAuth 端点,例如 /oauth/token,另一个用于其他所有端点。

      为 OAuth 端点创建的过滤器链采用您通过 ClientDetailsServiceConfigurer 指定的 UserDetailsService 并将其应用于您指定的 AuthenticationManager

      如果我将您的配置放入我的 IDE 中,然后执行以下操作:

      curl --user clientapp:SECRET localhost:8080/oauth/token -dgrant_type=client_credentials

      然后它会带着一个令牌回来就好了。

      但是,对于其余请求,它不会将这些客户端应用到 AuthenticationManager。这样做的原因是,对于授权服务器,通常有两种不同类型的用户:客户端和最终用户。客户端需要使用 OAuth API,而用户只需要使用 Web 应用程序(登录等)。

      这意味着如果你尝试去做:

      curl --user clientapp:SECRET localhost:8080

      这行不通。该组用户尚未应用于该过滤器链。

      如果您有非 OAuth2 端点,那么您需要自己在 UserDetailsService 中指定一组用户。如果没有这个,当您尝试使用 basic 访问这些端点时,将没有用户可供查找。

      此外,默认的AuthenticationManager 会自动获取您的PasswordEncoder。因此,您可以这样做,而不是您的 WebSecurityConfiguration#configure 方法:

      @Bean
      public UserDetailsService userDetailsService() {
          return new InMemoryUserDetailsService(User
              .withUsername("user")
              .password(passwordEncoder().encode("password"))
              .role("USER")
              .build());
      }
      

      (如果您需要做一些更复杂的事情,您也可以自定义 AuthenticationManager。)

      尝试使用您发布的应用程序(再次更改上述WebSecurityConfiguration 中的configure 方法),我也可以这样做:

      curl --user user:password localhost:8080
      

      【讨论】:

      • 不幸的是 curl --user clientapp:SECRET localhost:8080 不起作用
      【解决方案3】:

      在您的 WebSecurityConfiguration 中,authenticationManagerBean() 应该返回您自己的 AuthenticationManager bean 实例,而不是 super.authenticationManager()?

      【讨论】:

      • 不,我用我的设置覆盖了 configure() 方法
      猜你喜欢
      • 2022-01-09
      • 2012-09-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-25
      • 2016-12-07
      • 2019-12-16
      相关资源
      最近更新 更多