我正在尝试使用JWT授权服务器配置Spring Boot 2,OAuth2,这需要执行以下操作:
为了执行#3,我试图通过给它一个自定义PreAuthenticatedAuthenticationProvider
来自定义UserDetailsService
,并且AuthenticationManagerBuilder
bean必须同时传递自定义的{{1 }}和PreAuthenticatedAuthenticationProvider
。
假设我正朝着正确的方向前进,这是我的配置代码:
DaoAuthenticationProvider
在@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
UserDetailsService userDetailsService;
@Autowired
PasswordEncoder passwordEncoder;
//implements AuthenticationUserDetailsService<PreAuthenticatedAuthenticationToken>
@Autowired
CustomPreauthenticatedUserDetailsService customPreauthenticatedUserDetailsService;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/actuator/**").permitAll()
.antMatchers("/swagger-ui**","/webjars/**","/swagger-resources/**", "/v2/**").permitAll()
.antMatchers("/oauth/token/revokeById/**").permitAll()
.antMatchers("/oauth/token/**").permitAll()
.anyRequest().authenticated()
.and().csrf().disable();
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder authenticationManager) throws Exception {
authenticationManager.authenticationProvider(preauthAuthProvider());
authenticationManager.authenticationProvider(dbAuthProvider());
}
@Bean
@Qualifier(value = "authenticationManagerBean")
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Bean(value="preAuthProvider")
public PreAuthenticatedAuthenticationProvider preauthAuthProvider() {
PreAuthenticatedAuthenticationProvider preauthAuthProvider = new PreAuthenticatedAuthenticationProvider();
LOGGER.info("Setting customPreauthenticatedUserDetailsService");
preauthAuthProvider.setPreAuthenticatedUserDetailsService(customPreauthenticatedUserDetailsService);
return preauthAuthProvider;
}
@Bean(value="dbAuthProvider")
public DaoAuthenticationProvider dbAuthProvider() {
DaoAuthenticationProvider dbAuthProvider = new DaoAuthenticationProvider();
dbAuthProvider.setUserDetailsService(userDetailsService);
dbAuthProvider.setPasswordEncoder(passwordEncoder);
return dbAuthProvider;
}
}
端:
AuthorizationServerConfig
启动该应用程序后,我发现出现问题的第一个迹象是:
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
private static final Integer ACCESS_TOKEN_VALIDITY_SECONDS = 300;
private static final Integer REFRESH_TOKEN_VALIDITY_SECONDS = 60 * 60 * 24 * 60;
@Autowired
public AuthorizationServerConfig(AuthenticationManager authenticationManagerBean, PasswordEncoder passwordEncoder, CustomTokenEnhancer customTokenEnhancer, TokenStore tokenStore, JwtAccessTokenConverter accessTokenConverter) {
this.authenticationManagerBean = authenticationManagerBean;
this.passwordEncoder = passwordEncoder;
this.customTokenEnhancer = customTokenEnhancer;
this.tokenStore = tokenStore;
this.accessTokenConverter = accessTokenConverter;
}
private AuthenticationManager authenticationManagerBean;
private PasswordEncoder passwordEncoder;
private CustomTokenEnhancer customTokenEnhancer;
private JwtAccessTokenConverter accessTokenConverter;
private TokenStore tokenStore;
@Override
public void configure(AuthorizationServerSecurityConfigurer authorizationServerSecurityConfigurer) {
authorizationServerSecurityConfigurer.tokenKeyAccess("permitAll()").checkTokenAccess("isAuthenticated()");
}
@Override
public void configure(ClientDetailsServiceConfigurer clientDetailsServiceConfigurer) throws Exception {
clientDetailsServiceConfigurer.inMemory().withClient("someclient")
.authorizedGrantTypes("password", "refresh_token")
.scopes("read", "write").accessTokenValiditySeconds(ACCESS_TOKEN_VALIDITY_SECONDS)
.refreshTokenValiditySeconds(REFRESH_TOKEN_VALIDITY_SECONDS)
.secret(this.passwordEncoder.encode("somepassword"));
}
@Override
public void configure(final AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
tokenEnhancerChain.setTokenEnhancers(Arrays.asList(customTokenEnhancer, accessTokenConverter));
endpoints.tokenStore(tokenStore).tokenEnhancer(tokenEnhancerChain)
.authenticationManager(this.authenticationManagerBean);
}
}
奇怪的是,这似乎是一个谎言,或者是在谈论其他事情,因为当我尝试使用用户名和密码登录时,它可以工作,并且我同时获得刷新和访问令牌。调试器显示s.c.a.w.c.WebSecurityConfigurerAdapter$3 : No authenticationProviders and no parentAuthenticationManager defined. Returning null.
拥有我的自定义身份验证提供程序类,并将它们用于身份验证。
但是,当我尝试使用刷新令牌检索新令牌时,调试器显示该应用似乎采用了不同的ProviderManager
路径-该ProviderManager
仅具有ProviderManager
在其列表中,并且该提供程序不是我配置的提供程序。该PreAuthenticatedAuthenticationProvider
试图从PreAuthenticatedAuthenticationProvider
检索UserDetailsService
,结果是错误:
WebSecurityConfigurerAdapter$UserDetailsServiceDelegator
那么,我缺少什么配置步骤?为什么刷新令牌调用转到其他地方?我要传递的2019-06-08 13:27:24.764 ERROR 8731 --- [nio-8080-exec-3] o.s.s.o.provider.endpoint.TokenEndpoint : Handling error: IllegalStateException, UserDetailsService is required.
是authenticationManagerBean
吗?