spring oauth2 中带有自定义 ClientDetailsS​​ervice 的 StackOverflowError

StackOverflowError in spring oauth2 with custom ClientDetailsService

我自己实现了 ClientDetailsS​​ervice:

@Service
public class JpaClientDetailsService implements ClientDetailsService {
    @Autowired
    private ClientRepository clientRepositoy;

    @Override
    public ClientDetails loadClientByClientId(String clientId) throws ClientRegistrationException {
        ClientDetails client = clientRepositoy.findOne(clientId);
        if (client == null) {
            throw new ClientRegistrationException(String.format("Client with id %s not found", clientId));
        }
        return client;
    }
}

ClientRepository 是一个标准的 JpaRepository。

我这样配置了一个 AuthorizationServerConfigurerAdapter:

@Configuration
@EnableAuthorizationServer
@EnableResourceServer
public class OAuth2ServerConfig extends AuthorizationServerConfigurerAdapter {
    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private ClientDetailsService clientDetailsService;

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.authenticationManager(authenticationManager);
    }

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.withClientDetails(clientDetailsService);
    }
}

但是当我去 http://localhost:9999/oauth/authorize?response_type=code&client_id=lipton 时,我得到一个

java.lang.WhosebugError: null. Spring loops on com.sun.proxy.$Proxy81.loadClientByClientId(Unknown Source).

我不明白为什么。

我不明白为什么,但是如果我直接注入我的 bean 而不是注入接口,它就可以工作:

public class OAuth2ServerConfig extends AuthorizationServerConfigurerAdapter {
...
  @Autowired
  private JpaClientDetailsService clientDetailsService;
...

如果我用@Primary 注释来注释我的服务,它也可以工作:

@Service
@Primary
public class JpaClientDetailsService implements ClientDetailsService {

我遇到了类似的问题。最后我解决了错误,当我给我的 clientDetailsS​​ervice 另一个名字,即 myClientDetailsS​​ervice 然后在 AuthorizationServerConfig class:

中按名称注入这个
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {

    @Resource(name = "myClientDetailsService")
    private ClientDetailsService clientDetailsService;
...

我认为如果我自己的 ClientDetailsS​​ervice 实现尚未创建 Spring 将某种代理注入 AuthorizationServerConfig。

因此,如果您想解决此类错误,您必须确保 Spring 在中注入正确的 ClientDetailsS​​ervice 授权服务器配置。如果您:

,您可以实现这一目标
  1. 提供 spring 有关您自己的 ClientDetailsS​​ervice 偏好的信息(Arnaud 回答),或
  2. 按名称注入此服务

最终对我有用的是将 ClientDetailsS​​ervice @Bean 添加到 @EnableAuthorizationServer class:

@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfiguration implements AuthorizationServerConfigurer {
    ...
    @Autowired
    ClientDetailsService clientDetailsService;
    ...
    @Bean
    public ClientDetailsService clientDetailsService() {
        return new CustomClientDetailsServiceImpl();
    }
    ...
}

我会说最好的解决方案是明确的 - 如果你正在自动装配 clientDetailsS​​ervice - 那么就这样说。

@Autowired
ClientDetailsService myClientDetailsService;

@Override
public void configure(final AuthorizationServerEndpointsConfigurer endpoints) throws Exception {

        endpoints.setClientDetailsService(myClientDetailsService);
       ....
}

但是,我的问题略有不同,上述解决方案均无效。这是创造它的条件。 我创建了一个 CustomTokenEndpointAuthenticationFilter - 它需要一个 OAuth2RequestFactory 实例。 我通过调用 endpoints.getOAuth2RequestFactory(); 创建了我的 OAuth2RequestFactory 实例;在设置 clientDetailsS​​ervice 之前。

如果以这种方式创建 OAuth2RequestFactory,则会使用默认的 clientDetailsS​​ervice 创建 DefaultOAuth2RequestFactory,因此即使您稍后在 AuthorizationServerEndpointsConfigurer 中明确设置 clientDetailsS​​ervice,它也不会出现在您的自定义过滤器使用的 OAuth2RequestFactory 中。

总而言之,在这种极端情况下

public void configure(final AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
     oAuth2RequestFactory = endpoints.getOAuth2RequestFactory();
     endpoints.setClientDetailsService(myClientDetailsService);
    ...
    }

不会工作但是

public void configure(final AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.setClientDetailsService(myClientDetailsService);
 oAuth2RequestFactory = endpoints.getOAuth2RequestFactory();
...
}

会。

另一种确定的方法是创建您自己的 OAuth2RequestFatory

  oauth2RequestFactory = new DefaultTokenRequestFactory(myClientDetailsService);

我修复了在我的 costum ClientDetailsS​​ervice 中注释 @Primary 的问题:

@Service
@Primary
public class ClientDetailsServiceImp implements ClientDetailsService {