我想在Spring框架中提供TokenEndpoint类的自定义实现。
我已经复制了spring的TokenEndpoint类,并对所需的位置进行了更改。但是,当应用程序启动时,总是出现错误
Caused by: java.lang.IllegalStateException: TokenGranter must be provided
我在OAuthConfig中提供了TokenGranter的实现,但是spring并没有实现
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.pathMapping("/oauth/token", "/oauth/token/v1")
.tokenServices(tokenServices())
.tokenGranter(tokenGranter())
.authenticationManager(authenticationManager).tokenStore(tokenStore())
.tokenEnhancer(tokenEnhancer()).accessTokenConverter(accessTokenConverter());
}
@Bean
@Primary
public TokenGranter tokenGranter() {
TokenGranter tokenGranter = null;
if (tokenGranter == null) {
tokenGranter = new TokenGranter() {
private CompositeTokenGranter delegate;
@Override
public OAuth2AccessToken grant(String grantType, TokenRequest tokenRequest) {
if (delegate == null) {
delegate = new CompositeTokenGranter(getDefaultTokenGranters());
}
return delegate.grant(grantType, tokenRequest);
}
};
}
return tokenGranter;
}
我什至尝试在我的自定义TokenEndpoint类中提供此实现。 目前,自定义TokenEndpoint的实现与Spring的TokenEndpoint完全相同。
OAuth2AccessToken token = getTokenGranter().grant(tokenRequest.getGrantType(), tokenRequest);
private List<TokenGranter> getDefaultTokenGranters() {
ClientDetailsService clientDetails = clientDetailsService();
AuthorizationServerTokenServices tokenServices = tokenServices();
AuthorizationCodeServices authorizationCodeServices = authorizationCodeServices();
OAuth2RequestFactory requestFactory = requestFactory();
List<TokenGranter> tokenGranters = new ArrayList<TokenGranter>();
tokenGranters.add(new AuthorizationCodeTokenGranter(tokenServices, authorizationCodeServices, clientDetails,
requestFactory));
tokenGranters.add(new RefreshTokenGranter(tokenServices, clientDetails, requestFactory));
ImplicitTokenGranter implicit = new ImplicitTokenGranter(tokenServices, clientDetails, requestFactory);
tokenGranters.add(implicit);
tokenGranters.add(new ClientCredentialsTokenGranter(tokenServices, clientDetails, requestFactory));
if (authenticationManager != null) {
tokenGranters.add(new ResourceOwnerPasswordTokenGranter(authenticationManager, tokenServices, clientDetails,
requestFactory));
}
return tokenGranters;
}
private DefaultTokenServices createDefaultTokenServices() {
DefaultTokenServices tokenServices = new DefaultTokenServices();
tokenServices.setTokenStore(tokenStore());
tokenServices.setSupportRefreshToken(true);
tokenServices.setReuseRefreshToken(true);
tokenServices.setClientDetailsService(clientDetailsService());
tokenServices.setTokenEnhancer(tokenEnhancer());
addUserDetailsService(tokenServices, new CustomDetailsService());
return tokenServices;
}
private ClientDetailsService clientDetailsService() {
ClientDetailsService clientDetailsService = null;
clientDetailsService = new InMemoryClientDetailsService();
addUserDetailsService(createDefaultTokenServices(), new CustomDetailsService());
return clientDetailsService;
}
private void addUserDetailsService(DefaultTokenServices tokenServices, UserDetailsService userDetailsService) {
if (userDetailsService != null) {
PreAuthenticatedAuthenticationProvider provider = new PreAuthenticatedAuthenticationProvider();
provider.setPreAuthenticatedUserDetailsService(new UserDetailsByNameServiceWrapper<PreAuthenticatedAuthenticationToken>(
userDetailsService));
tokenServices
.setAuthenticationManager(new ProviderManager(Arrays.<AuthenticationProvider> asList(provider)));
}
}
private AuthorizationCodeServices authorizationCodeServices() {
AuthorizationCodeServices authorizationCodeServices = new InMemoryAuthorizationCodeServices();
return authorizationCodeServices;
}
private OAuth2RequestFactory requestFactory() {
OAuth2RequestFactory requestFactory = new DefaultOAuth2RequestFactory(clientDetailsService());
return requestFactory;
}
@Bean
public JwtTokenStore tokenStore() {
JwtTokenStore jwtTokenStore = new JwtTokenStore(accessTokenConverter());
return jwtTokenStore;
}
@Bean
@Primary
public AuthorizationServerTokenServices tokenServices() {
final DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
defaultTokenServices.setAccessTokenValiditySeconds(-1);
defaultTokenServices.setTokenStore(tokenStore());
return defaultTokenServices;
}
@Bean
public TokenEnhancer tokenEnhancer() {
return new CustomTokenEnhancer();
}
@Bean
public JwtAccessTokenConverter accessTokenConverter() {
final JwtAccessTokenConverter converter = new JwtAccessTokenConverter() {
@Override
public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
return accessToken;
}
};
return converter;
}
我已经尝试了几天,但没有任何运气。因此,我们将不胜感激。
答案 0 :(得分:0)
您为什么需要再次实现TokenEndpoint
?
您可以创建一个TokenGranter
bean并将其注入默认端点。
getDefaultTokenGranters()
方法在哪里?
您似乎没有AuthorizationServerEndpointsConfigurer
源代码的完整副本。
更新:
如果您想自定义令牌响应,请使用TokenEnhancer
。
例如:
public class CustomTokenEnhancer implements TokenEnhancer {
@Override
public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
OurUser user = (OurUser) authentication.getPrincipal();
final Map<String, Object> additionalInfo = new HashMap<>();
Map<String, Object> userDetails = new HashMap<>();
userDetails.put(USERID, user.getId().getId());
userDetails.put(NAME, user.getName());
userDetails.put(MOBILE, user.getMobile());
userDetails.put(EMAIL, user.getEmail());
additionalInfo.put(USERINFO, userDetails);
// Set additional information in token for retriving in #org.springframework.security.oauth2.provider.endpoint.CheckTokenEndpoint
((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInfo);
return accessToken;
}
}
在OAuth2配置中:
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
super.configure(endpoints);
endpoints.
.....
// Include additional information to OAuth2 Access token with custom token enhancer
.tokenEnhancer(tokenEnhancer());
}
@Bean
public TokenEnhancer tokenEnhancer() {
return new CustomTokenEnhancer();
}
答案 1 :(得分:0)
我知道这个问题已经很老了,但是我遇到了同样的问题,并且没有找到有关自定义TokenEndpoint的完整指南。我无法使用TokenEnhancer,因为我需要更改响应的标头。因此,这是为我工作的版本。
您照常定义覆盖的控制器:
@RequestMapping(value = "/oauth/token")
public class CustomTokenEndpoint extends TokenEndpoint {
@PostMapping
public ResponseEntity<OAuth2AccessToken> postAccessToken(
Principal principal,
@RequestParam Map<String, String> parameters
) throws HttpRequestMethodNotSupportedException {
ResponseEntity<OAuth2AccessToken> defaultResponse = super.postAccessToken(principal, parameters);
// do some work
return defaultResponse;
}
}
您需要创建自己的TokenEndpoint bean:
@Bean
@Primary
public TokenEndpoint tokenEndpoint(AuthorizationServerEndpointsConfiguration conf) {
TokenEndpoint tokenEndpoint = new CustomTokenEndpoint();
tokenEndpoint.setClientDetailsService(conf.getEndpointsConfigurer().getClientDetailsService());
tokenEndpoint.setProviderExceptionHandler(conf.getEndpointsConfigurer().getExceptionTranslator());
tokenEndpoint.setTokenGranter(conf.getEndpointsConfigurer().getTokenGranter());
tokenEndpoint.setOAuth2RequestFactory(conf.getEndpointsConfigurer().getOAuth2RequestFactory());
tokenEndpoint.setOAuth2RequestValidator(conf.getEndpointsConfigurer().getOAuth2RequestValidator());
tokenEndpoint.setAllowedRequestMethods(conf.getEndpointsConfigurer().getAllowedTokenEndpointRequestMethods());
return tokenEndpoint;
}
这是踢脚线。您需要允许覆盖application.properties
中的spring bean:
spring.main.allow-bean-definition-overriding: true
希望这对某人有帮助