我自己实现了ClientDetailsService:
@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.StackOverflowError: 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 {
我不明白为什么,但如果我直接注入我的bean而不是注入接口,它的工作原理如下:
public class OAuth2ServerConfig extends AuthorizationServerConfigurerAdapter {
...
@Autowired
private JpaClientDetailsService clientDetailsService;
...
如果我用@Primary注释注释我的服务,它也有效:
@Service
@Primary
public class JpaClientDetailsService implements ClientDetailsService {
我有类似的问题。最后,当我向clientDetailsService提供另一个名称,即myClientDetailsService,然后在AuthorizationServerConfig类中按名称注入时,我解决了错误:
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Resource(name = "myClientDetailsService")
private ClientDetailsService clientDetailsService;
...
我认为如果我自己的ClientDetailsService实现还没有创建Spring注入AuthorizationServerConfig某种代理。
所以,如果你想解决这种错误,你一定要确定
Spring注入了适当的ClientDetailsService
AuthorizationServerConfig。如果您:
- 提供有关您自己的ClientDetailsService(Arnaud答案)的偏好的弹簧信息,或
- 按名称注入此服务
最终为我工作的是将ClientDetailsService @Bean添加到@EnableAuthorizationServer类:
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfiguration implements AuthorizationServerConfigurer {
...
@Autowired
ClientDetailsService clientDetailsService;
...
@Bean
public ClientDetailsService clientDetailsService() {
return new CustomClientDetailsServiceImpl();
}
...
}
我想说最好的解决方案是明确的 - 如果你是自动装载clientDetailsService - 然后这样说。
@Autowired
ClientDetailsService myClientDetailsService;
@Override
public void configure(final AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.setClientDetailsService(myClientDetailsService);
....
}
但是,我的问题略有不同,上述解决方案无效。以下是创建它的条件。
我创建了一个CustomTokenEndpointAuthenticationFilter - 它需要一个OAuth2RequestFactory实例。
我通过调用endpoints.getOAuth2RequestFactory()创建了我的OAuth2RequestFactory实例;在设置clientDetailsService之前。
如果以这种方式创建OAuth2RequestFactory,则使用默认的clientDetailsService创建DefaultOAuth2RequestFactory,因此即使稍后在AuthorizationServerEndpointsConfigurer中显式设置clientDetailsService,它也不会位于自定义Filter使用的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);