Spring Sprin OAuth2中TokenEndpoint的定制

Spring Sprin OAuth2中TokenEndpoint的定制,spring,spring-security,spring-security-oauth2,spring-oauth2,Spring,Spring Security,Spring Security Oauth2,Spring Oauth2,我想在Spring框架中提供TokenEndpoint类的自定义实现 我复制了spring的TokenEndpoint类,并对所需的位置进行了更改。但是当应用程序启动时,我总是得到错误 Caused by: java.lang.IllegalStateException: TokenGranter must be provided 我已经在OAuthConfig中提供了TokenGranter的实现,但spring并没有考虑到这一点 @Override public void configur

我想在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;
}
OAuth2AccessToken token=getTokenGranter().grant(tokenRequest.getGrantType(),tokenRequest);
私有列表getDefaultTokenGranters(){
ClientDetailsService clientDetails=ClientDetailsService();
AuthorizationServerTokenServices tokenServices=tokenServices();
AuthorizationCodeServices AuthorizationCodeServices=AuthorizationCodeServices();
OAuth2RequestFactory requestFactory=requestFactory();
List tokenGranters=new ArrayList();
添加(新授权代码TokenGranter)(tokenServices、authorizationCodeServices、clientDetails、,
),;
添加(新的RefreshTokenGranter(tokenServices、clientDetails、requestFactory));
ImplicitTokenGranter implicit=新ImplicitTokenGranter(令牌服务、clientDetails、requestFactory);
tokenGranters.add(隐式);
添加(新的ClientCredentialsTokenGranter(tokenServices、clientDetails、requestFactory));
如果(authenticationManager!=null){
添加(新资源所有者PasswordTokenGranter(authenticationManager、tokenServices、clientDetails、,
),;
}
返回授权人;
}
私有DefaultTokenServices createDefaultTokenServices(){
DefaultTokenServices tokenServices=新的DefaultTokenServices();
setTokenStore(tokenStore());
tokenServices.setSupportRefreshToken(true);
tokenServices.setreUserFreshToken(true);
setClientDetailsService(clientDetailsService());
setTokenEnhancer(tokenEnhancer());
addUserDetailsService(令牌服务,新的CustomDetailsService());
退货服务;
}
私有客户端详细信息服务客户端详细信息服务(){
ClientDetailsService ClientDetailsService=null;
clientDetailsService=新的InMemoryClientDetailsService();
addUserDetailsService(createDefaultTokenServices(),新的CustomDetailsService());
返回客户端详细信息服务;
}
私有void addUserDetailsService(DefaultTokenServices令牌服务,UserDetailsService UserDetailsService){
if(userDetailsService!=null){
PreAuthenticateAuthenticationProvider=新的PreAuthenticateAuthenticationProvider();
setPreAuthenticatedUserDetailsService(新的UserDetailsByNameServiceWrapper(
用户详细信息服务);
代币服务
.setAuthenticationManager(新的ProviderManager(Arrays.asList(provider));
}
}
私有授权CodeServices授权CodeServices(){
AuthorizationCodeServices AuthorizationCodeServices=新的InMemoryAuthorizationCodeServices();
返回授权代码服务;
}
私有OAuth2RequestFactory requestFactory(){
OAuth2RequestFactory requestFactory=新的默认OAuth2RequestFactory(clientDetailsService());
退货申请工厂;
}
@豆子
公共JwtTokenStore tokenStore(){
JwtTokenStore JwtTokenStore=新的JwtTokenStore(accessTokenConverter());
返回jwtTokenStore;
}
@豆子
@初级的
公共授权服务器令牌服务令牌服务(){
final DefaultTokenServices DefaultTokenServices=新的DefaultTokenServices();
defaultTokenServices.setAccessTokenValiditySeconds(-1);
setTokenStore(tokenStore());
返回服务;
}
@豆子
公共令牌增强器令牌增强器(){
返回新的CustomTokenEnhancer();
}
@豆子
公共JwtAccessTokenConverter accessTokenConverter(){
最终JwtAccessTokenConverter=新JwtAccessTokenConverter(){
@凌驾
公共OAuth2AccessToken增强(OAuth2AccessToken accessToken,OAuth2Authentication身份验证){
返回accessToken;
}
};
回流转换器;
}

我已经想了好几天了,但是运气不好。因此,任何帮助都将不胜感激。

为什么您需要再次实现
TokenEndpoint

您可以创建
TokenGranter
bean并将其注入默认端点

哪里是
getDefaultTokenGranters()
方法

看起来您的
authorizationServerEndpointsConfiger
源代码的副本不完整

更新

如果要自定义令牌响应,请使用
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;
    }

}

我知道这个问题已经很老了,但我遇到了同样的问题,没有找到一个关于定制令牌端点的完整指南。我无法使用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;
  }
}
这是踢球的人。您需要允许在
应用程序中覆盖Springbean。属性

spring.main.allow-bean-definition-overriding: true

希望这对某人有所帮助

我的目标是定制使用访问令牌返回响应的方式。因此,我正在实现令牌端点。我为AuthorizationServerEndpointsConfiguration中所有必需的方法提供了实现。没有贴在这里,因为方法太多了。我的最终目标是调整从端点返回响应的方式,而不是提供新的TokenGranter。您应该使用TokenEnhancer。我复制了spring的TokenEndpoint类,并对所需位置进行了更改。这是否意味着您有两个
标记端点  @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;
  }
spring.main.allow-bean-definition-overriding: true