带有自定义 AuthenticationManager 的 SpringSecurity BasicAuthenticationFilter
SpringSecurity BasicAuthenticationFilter with custom AuthenticationManager
对于 BasicAuthenticationFilter,我正在尝试注入我自己的 AuthenticationManager。
但是当我调试启动时,我总是发现 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);
}
感谢您的帮助。
在您的 WebSecurityConfiguration 中,authenticationManagerBean() 应该 return 您自己的 AuthenticationManager bean 实例,而不是 super.authenticationManager()?
根据您给定的配置,您实际上会得到 BasicAuthenticationFilter
的两个实例。两者都应该让你的 AuthenticationManager
就好了。但是,对于其中一个,它是父 AuthenticationManager
,这意味着您还应该在调试器中检查 authenticationManager.parent
属性。
您的 AuthenticationManager
可能存在一些问题。
Spring Security OAuth 将创建两个过滤器链(随后是两个 BasicAuthenticationFilter
、两个 AuthenticationManager
);一个用于 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
问题是我在build.gradle
中使用了错误的包
为了解决这个问题,我添加了以下包:
build.gradle
implementation("org.springframework.security.oauth.boot:spring-security-oauth2-autoconfigure:${springBootVersion}")
对于 BasicAuthenticationFilter,我正在尝试注入我自己的 AuthenticationManager。 但是当我调试启动时,我总是发现 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);
}
感谢您的帮助。
在您的 WebSecurityConfiguration 中,authenticationManagerBean() 应该 return 您自己的 AuthenticationManager bean 实例,而不是 super.authenticationManager()?
根据您给定的配置,您实际上会得到 BasicAuthenticationFilter
的两个实例。两者都应该让你的 AuthenticationManager
就好了。但是,对于其中一个,它是父 AuthenticationManager
,这意味着您还应该在调试器中检查 authenticationManager.parent
属性。
您的 AuthenticationManager
可能存在一些问题。
Spring Security OAuth 将创建两个过滤器链(随后是两个 BasicAuthenticationFilter
、两个 AuthenticationManager
);一个用于 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
问题是我在build.gradle
中使用了错误的包为了解决这个问题,我添加了以下包:
build.gradle
implementation("org.springframework.security.oauth.boot:spring-security-oauth2-autoconfigure:${springBootVersion}")