spring security oauth2 ClassCastException 配置 DefaultTokenServices
spring security oauth2 ClassCastException configuring DefaultTokenServices
我正在尝试 运行 使用 spring 引导和 spring 安全 oauth 的示例应用程序,其中配置了 JdbcTokenStore 和具有无限生命周期访问令牌的 DefaultTokenServices。
运行 此应用程序使用 gradle bootRun,应用程序无法启动并抛出 "Caused by: java.lang.ClassCastException: com.sun.proxy.$Proxy51 cannot be cast to org.springframework.security.oauth2.provider.token.DefaultTokenServices"
为什么 DefaultTokenServices bean 周围有一个代理?
奇怪的是 - 运行使用 InMemoryTokenStore 连接应用程序...一切正常(参见内存分支)。
我的应用程序中也有类似的异常,当将 spring oauth 版本从 2.0.7.RELEASE 更改为 2.0.3.RELEASE 时,它起作用了。也许这是最新版本中的错误?
编辑: 从错误看来问题与 spring 创建的代理有关。当我将代理类型更改为 CGLIB 而不是默认动态代理时,它也适用于 2.0.7 版。这个设置可以通过 proxyTargetClass 属性 @EnableTransactionManagement(proxyTargetClass = true)
来设置
但是这个解决方案对我没有吸引力,因为我更喜欢默认代理方法而不是 CGLIB。这里还有一篇解释代理方法的文章http://thecafetechno.com/tutorials/spring/spring-proxying-mechanisms/
快速浏览一下 DefaultTokenService 就会发现它带有 @Transactional 注释。 Spring 将把它包装在一个代理中来为交易提供服务 - 因此您需要通过其接口与 class 进行交互。
对于您的 tokenService bean:
@Bean
public DefaultTokenServices tokenServices() {
final DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
defaultTokenServices.setAccessTokenValiditySeconds(-1);
defaultTokenServices.setTokenStore(tokenStore());
return defaultTokenServices;
}
尝试将其更改为:
@Bean
public AuthorizationServerTokenServices tokenServices() {
final DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
defaultTokenServices.setAccessTokenValiditySeconds(-1);
defaultTokenServices.setTokenStore(tokenStore());
return defaultTokenServices;
}
这适用于 2.0 版。7.RELEASE
@Primary
@Bean
protected AuthorizationServerTokenServices tokenServices() throws Exception{
将 DefaultTokenServices 更改为 AuthorizationServerTokenServices 后,Spring 将抛出错误:
No qualifying bean of type
[org.springframework.security.oauth2.provider.token.ResourceServerTokenServices]
is defined: expected single matching bean but found 3:
defaultAuthorizationServerTokenServices,consumerTokenServices,tokenServices"}}
我在以下组合中使用 2.0.9.RELEASE 时遇到了同样的问题:
pom.xml:
...
<spring.version>4.1.4.RELEASE</spring.version>
<spring-security.version>3.2.5.RELEASE</spring-security.version>
<spring-security-oauth2.version>2.0.9.RELEASE</spring-security-oauth2.version>
...
并有相同的异常。
降级到
...
<spring-security-oauth2.version>2.0.3.RELEASE</spring-security-oauth2.version>
...
为我解决了问题。
添加
<aop:config proxy-target-class="true"/>
在您的 spring 配置上。
我正在尝试 运行 使用 spring 引导和 spring 安全 oauth 的示例应用程序,其中配置了 JdbcTokenStore 和具有无限生命周期访问令牌的 DefaultTokenServices。
运行 此应用程序使用 gradle bootRun,应用程序无法启动并抛出 "Caused by: java.lang.ClassCastException: com.sun.proxy.$Proxy51 cannot be cast to org.springframework.security.oauth2.provider.token.DefaultTokenServices"
为什么 DefaultTokenServices bean 周围有一个代理?
奇怪的是 - 运行使用 InMemoryTokenStore 连接应用程序...一切正常(参见内存分支)。
我的应用程序中也有类似的异常,当将 spring oauth 版本从 2.0.7.RELEASE 更改为 2.0.3.RELEASE 时,它起作用了。也许这是最新版本中的错误?
编辑: 从错误看来问题与 spring 创建的代理有关。当我将代理类型更改为 CGLIB 而不是默认动态代理时,它也适用于 2.0.7 版。这个设置可以通过 proxyTargetClass 属性 @EnableTransactionManagement(proxyTargetClass = true)
但是这个解决方案对我没有吸引力,因为我更喜欢默认代理方法而不是 CGLIB。这里还有一篇解释代理方法的文章http://thecafetechno.com/tutorials/spring/spring-proxying-mechanisms/
快速浏览一下 DefaultTokenService 就会发现它带有 @Transactional 注释。 Spring 将把它包装在一个代理中来为交易提供服务 - 因此您需要通过其接口与 class 进行交互。
对于您的 tokenService bean:
@Bean
public DefaultTokenServices tokenServices() {
final DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
defaultTokenServices.setAccessTokenValiditySeconds(-1);
defaultTokenServices.setTokenStore(tokenStore());
return defaultTokenServices;
}
尝试将其更改为:
@Bean
public AuthorizationServerTokenServices tokenServices() {
final DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
defaultTokenServices.setAccessTokenValiditySeconds(-1);
defaultTokenServices.setTokenStore(tokenStore());
return defaultTokenServices;
}
这适用于 2.0 版。7.RELEASE
@Primary
@Bean
protected AuthorizationServerTokenServices tokenServices() throws Exception{
将 DefaultTokenServices 更改为 AuthorizationServerTokenServices 后,Spring 将抛出错误:
No qualifying bean of type [org.springframework.security.oauth2.provider.token.ResourceServerTokenServices] is defined: expected single matching bean but found 3: defaultAuthorizationServerTokenServices,consumerTokenServices,tokenServices"}}
我在以下组合中使用 2.0.9.RELEASE 时遇到了同样的问题:
pom.xml:
...
<spring.version>4.1.4.RELEASE</spring.version>
<spring-security.version>3.2.5.RELEASE</spring-security.version>
<spring-security-oauth2.version>2.0.9.RELEASE</spring-security-oauth2.version>
...
并有相同的异常。
降级到
...
<spring-security-oauth2.version>2.0.3.RELEASE</spring-security-oauth2.version>
...
为我解决了问题。
添加
<aop:config proxy-target-class="true"/>
在您的 spring 配置上。