[英]No AuthenticationProvider found on refresh token - Spring OAuth2 java config
我有一個Spring Boot項目,在其中配置了部分起作用的Spring OAuth2身份驗證過程。 我可以驗證OK,但是當我嘗試獲取刷新令牌時會出現異常。
OAuth配置:
@Configuration
public class OAuth2ServerConfiguration {
private static final String RESOURCE_ID = "xxx";
@Configuration
@EnableResourceServer
protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
@Override
public void configure(ResourceServerSecurityConfigurer resources) {
resources.resourceId(RESOURCE_ID);
}
@Override
public void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/api/**").authenticated();
}
}
@Configuration
@EnableAuthorizationServer
protected static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
@Value("${clientDetailsService.clientName}")
private String clientName;
@Value("${clientDetailsService.clientSecret}")
private String clientSecret;
@Autowired
@Qualifier("authenticationManager")
private AuthenticationManager authenticationManager;
@Autowired
private ClientDetailsService clientDetailsService;
@Autowired
@Qualifier("tokenServices")
private AuthorizationServerTokenServices tokenServices;
@Autowired
@Qualifier("codeServices")
private AuthorizationCodeServices codeServices;
@Autowired
@Qualifier("requestFactory")
private OAuth2RequestFactory requestFactory;
@Autowired
@Qualifier("tokenGranter")
private TokenGranter tokenGranter;
private final TokenStore tokenStore = new InMemoryTokenStore();
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.setClientDetailsService(clientDetailsService);
endpoints.tokenServices(tokenServices)
.tokenStore(tokenStore)
.authorizationCodeServices(codeServices)
.authenticationManager(authenticationManager)
.requestFactory(requestFactory)
.tokenGranter(tokenGranter);
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.withClientDetails(clientDetailsService);
}
@Bean(name = "tokenGranter")
@Primary
public TokenGranter tokenGranter() {
final List<TokenGranter> tokenGranters = new ArrayList<TokenGranter>();
tokenGranters.add(new AuthorizationCodeTokenGranter(tokenServices, codeServices, clientDetailsService, requestFactory));
tokenGranters.add(new RefreshTokenGranter(tokenServices, clientDetailsService, requestFactory));
tokenGranters.add(new ImplicitTokenGranter(tokenServices, clientDetailsService, requestFactory));
tokenGranters.add(new ClientCredentialsTokenGranter(tokenServices, clientDetailsService, requestFactory));
tokenGranters.add(new CustomTokenGranter(authenticationManager, tokenServices, clientDetailsService, requestFactory));
return new CompositeTokenGranter(tokenGranters);
}
@Bean
@Primary
public ClientDetailsService clientDetailsService(){
final InMemoryClientDetailsServiceBuilder builder = new InMemoryClientDetailsServiceBuilder();
builder.withClient(clientName)
.authorizedGrantTypes("password", "refresh_token")
.authorities("USER")
.scopes("read", "write")
.resourceIds(RESOURCE_ID)
.secret(clientSecret);
try {
return builder.build();
} catch (final Exception e) {
e.printStackTrace();
}
return null;
}
@Bean(name = "tokenServices")
@Primary
public AuthorizationServerTokenServices tokenServices() {
final DefaultTokenServices tokenServices = new DefaultTokenServices();
tokenServices.setSupportRefreshToken(true);
tokenServices.setClientDetailsService(clientDetailsService);
tokenServices.setTokenStore(tokenStore);
tokenServices.setAuthenticationManager(authenticationManager);
return tokenServices;
}
@Bean(name = "requestFactory")
@Primary
public OAuth2RequestFactory requestFactory() {
return new DefaultOAuth2RequestFactory(clientDetailsService);
}
@Bean(name = "codeServices")
@Primary
public AuthorizationCodeServices authorizationCodeServices() {
return new InMemoryAuthorizationCodeServices();
}
}
我還定義了一些自定義組件,例如自定義令牌授予者,自定義身份驗證提供程序等。如有必要,我將發布它們。
正如我所說,身份驗證流程可以正常運行。 當我發布到/ oauth / token時,我得到一個令牌和一個刷新令牌,但是當我嘗試將我的刷新令牌交換為一個新令牌時(通過使用grant_type = refresh_token POST http:// localhost:8080 / oauth / token , refresh_token =我的刷新令牌)出現異常:
找不到org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken的AuthenticationProvider
在哪里設置身份驗證提供程序? 如何使Spring還將我的自定義身份驗證提供程序也用於刷新令牌?
我通過顯式定義PreAuthenticationProvider來解決此問題:
@Component("preAuthProvider")
public class CustomPreAuthProvider extends PreAuthenticatedAuthenticationProvider {
@Autowired
private AuthenticationUserDetailsService<PreAuthenticatedAuthenticationToken> userService;
public CustomPreAuthProvider(){
super();
}
@PostConstruct
public void init(){
super.setPreAuthenticatedUserDetailsService(userService);
}
}
然后是自定義用戶服務:
@Service
public class CustomPreAuthUserDetailsService implements AuthenticationUserDetailsService<PreAuthenticatedAuthenticationToken> {
@Override
public final UserDetails loadUserDetails(PreAuthenticatedAuthenticationToken token) {
...
}
}
並將此提供程序添加到oauth2配置中:
@Autowired
private AuthenticationProvider authenticationProvider;
@Autowired
@Qualifier("preAuthProvider")
private AuthenticationProvider preAuthProvider;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authenticationProvider).authenticationProvider(preAuthProvider);
}
我不能不同意Jesper的回答,但就我而言,該錯誤已得到修復,已刪除:
tokenServices.setAuthenticationManager(authenticationManager)
來自tokenService()
作為Jesper回答的一種替代方法,如果您想為此目的重用當前的UserDetailsService
,則可以使用與Spring對其DefaultTokenServices
相同的方式進行操作:
@Bean
public CustomTokenServices tokenServices() {
CustomTokenServices tokenServices = new CustomTokenServices();
tokenServices.setTokenStore(tokenStore());
tokenServices.setSupportRefreshToken(true);
tokenServices.setReuseRefreshToken(false);
tokenServices.setClientDetailsService(clientDetailsService);
tokenServices.setAuthenticationManager(createPreAuthProvider());
return tokenServices;
}
private ProviderManager createPreAuthProvider() {
PreAuthenticatedAuthenticationProvider provider = new PreAuthenticatedAuthenticationProvider();
provider.setPreAuthenticatedUserDetailsService(new UserDetailsByNameServiceWrapper<>(userDetailsService));
return new ProviderManager(Arrays.asList(provider));
}
UserDetailsService
自動連接到此@Configuration
類。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.