spring-security - spring security oauth + redis session,客户端登录时author服务报错
本文介绍了spring-security - spring security oauth + redis session,客户端登录时author服务报错的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
问 题
用spring security的oauth + redis session做服务认证,但在ui跳转到author服务认证后报错,错误信息如下,请问如何解决:
org.springframework.data.redis.serializer.SerializationException: Cannot deserialize; nested exception is org.springframework.core.serializer.support.SerializationFailedException: Failed to deserialize payload. Is the byte array a result of corresponding serialization for DefaultDeserializer?; nested exception is java.lang.ClassCastException: cannot assign instance of org.springframework.beans.factory.support.StaticListableBeanFactory to field org.springframework.aop.scope.DefaultScopedObject.beanFactory of type org.springframework.beans.factory.config.ConfigurableBeanFactory in instance of org.springframework.aop.scope.DefaultScopedObject
at org.springframework.data.redis.serializer.JdkSerializationRedisSerializer.deserialize(JdkSerializationRedisSerializer.java:81) ~[spring-data-redis-1.7.2.RELEASE.jar:na]
at org.springframework.data.redis.core.AbstractOperations.deserializeHashValue(AbstractOperations.java:335) ~[spring-data-redis-1.7.2.RELEASE.jar:na]
at org.springframework.data.redis.core.AbstractOperations.deserializeHashMap(AbstractOperations.java:279) ~[spring-data-redis-1.7.2.RELEASE.jar:na]
at org.springframework.data.redis.core.DefaultHashOperations.entries(DefaultHashOperations.java:227) ~[spring-data-redis-1.7.2.RELEASE.jar:na]
at org.springframework.data.redis.core.DefaultBoundHashOperations.entries(DefaultBoundHashOperations.java:102) ~[spring-data-redis-1.7.2.RELEASE.jar:na]
at org.springframework.session.data.redis.RedisOperationsSessionRepository.getSession(RedisOperationsSessionRepository.java:432) ~[spring-session-1.2.1.RELEASE.jar:na]
at org.springframework.session.data.redis.RedisOperationsSessionRepository.onMessage(RedisOperationsSessionRepository.java:519) ~[spring-session-1.2.1.RELEASE.jar:na]
at org.springframework.data.redis.listener.RedisMessageListenerContainer.executeListener(RedisMessageListenerContainer.java:249) [spring-data-redis-1.7.2.RELEASE.jar:na]
at org.springframework.data.redis.listener.RedisMessageListenerContainer.processMessage(RedisMessageListenerContainer.java:239) [spring-data-redis-1.7.2.RELEASE.jar:na]
at org.springframework.data.redis.listener.RedisMessageListenerContainer$1.run(RedisMessageListenerContainer.java:967) [spring-data-redis-1.7.2.RELEASE.jar:na]
at java.lang.Thread.run(Thread.java:745) [na:1.8.0_74]
Caused by: org.springframework.core.serializer.support.SerializationFailedException: Failed to deserialize payload. Is the byte array a result of corresponding serialization for DefaultDeserializer?; nested exception is java.lang.ClassCastException: cannot assign instance of org.springframework.beans.factory.support.StaticListableBeanFactory to field org.springframework.aop.scope.DefaultScopedObject.beanFactory of type org.springframework.beans.factory.config.ConfigurableBeanFactory in instance of org.springframework.aop.scope.DefaultScopedObject
at org.springframework.core.serializer.support.DeserializingConverter.convert(DeserializingConverter.java:78) ~[spring-core-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.springframework.core.serializer.support.DeserializingConverter.convert(DeserializingConverter.java:36) ~[spring-core-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.springframework.data.redis.serializer.JdkSerializationRedisSerializer.deserialize(JdkSerializationRedisSerializer.java:79) ~[spring-data-redis-1.7.2.RELEASE.jar:na]
... 10 common frames omitted
Caused by: java.lang.ClassCastException: cannot assign instance of org.springframework.beans.factory.support.StaticListableBeanFactory to field org.springframework.aop.scope.DefaultScopedObject.beanFactory of type org.springframework.beans.factory.config.ConfigurableBeanFactory in instance of org.springframework.aop.scope.DefaultScopedObject
at java.io.ObjectStreamClass$FieldReflector.setObjFieldValues(ObjectStreamClass.java:2133) ~[na:1.8.0_74]
at java.io.ObjectStreamClass.setObjFieldValues(ObjectStreamClass.java:1305) ~[na:1.8.0_74]
at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:2006) ~[na:1.8.0_74]
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1924) ~[na:1.8.0_74]
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1801) ~[na:1.8.0_74]
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351) ~[na:1.8.0_74]
at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:2000) ~[na:1.8.0_74]
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1924) ~[na:1.8.0_74]
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1801) ~[na:1.8.0_74]
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351) ~[na:1.8.0_74]
at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:2000) ~[na:1.8.0_74]
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1924) ~[na:1.8.0_74]
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1801) ~[na:1.8.0_74]
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351) ~[na:1.8.0_74]
at java.io.ObjectInputStream.readArray(ObjectInputStream.java:1707) ~[na:1.8.0_74]
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1345) ~[na:1.8.0_74]
at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:2000) ~[na:1.8.0_74]
at java.io.ObjectInputStream.defaultReadObject(ObjectInputStream.java:501) ~[na:1.8.0_74]
at org.springframework.aop.framework.AdvisedSupport.readObject(AdvisedSupport.java:557) ~[spring-aop-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_74]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_74]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_74]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_74]
at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:1058) ~[na:1.8.0_74]
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1900) ~[na:1.8.0_74]
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1801) ~[na:1.8.0_74]
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351) ~[na:1.8.0_74]
at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:2000) ~[na:1.8.0_74]
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1924) ~[na:1.8.0_74]
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1801) ~[na:1.8.0_74]
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351) ~[na:1.8.0_74]
at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:2000) ~[na:1.8.0_74]
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1924) ~[na:1.8.0_74]
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1801) ~[na:1.8.0_74]
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351) ~[na:1.8.0_74]
at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:2000) ~[na:1.8.0_74]
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1924) ~[na:1.8.0_74]
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1801) ~[na:1.8.0_74]
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351) ~[na:1.8.0_74]
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:371) ~[na:1.8.0_74]
at org.springframework.core.serializer.DefaultDeserializer.deserialize(DefaultDeserializer.java:70) ~[spring-core-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.springframework.core.serializer.support.DeserializingConverter.convert(DeserializingConverter.java:73) ~[spring-core-4.3.2.RELEASE.jar:4.3.2.RELEASE]
... 12 common frames omitted
author服务代码如下
application.yml
server:
address: 127.0.0.1
port: 9001
context-path: /uaa
spring:
redis:
host: 192.168.1.190
freemarker:
suffix: .html
cache: false
security:
oauth2:
client:
client-id: app
client-secret: 1
scope: openid
auto-approve-scopes: .*
authorization:
check-token-access: permitAll()
user:
name: z
password: 1
AppAuth.java
@SpringBootApplication
@EnableAuthorizationServer
@RestController
@EnableRedisHttpSession
public class AppAuth {
public static void main(String[] args) {
SpringApplication.run(AppAuth.class, args);
}
@RequestMapping("/user")
public Principal user(Principal user) {
return user;
}
@Configuration
@Order(-20)
static class ConfigSecurity extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.formLogin().loginPage("/login").permitAll()
.and()
.requestMatchers()
.antMatchers("/", "/login", "/oauth/authorize", "/oauth/confirm_access")
.and()
.authorizeRequests()
.anyRequest().authenticated();
}
}
@Configuration
static class ConfigMvc extends WebMvcConfigurerAdapter {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("login").setViewName("login");
registry.addViewController("/").setViewName("hello");
}
}
}
login.html
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<form name="f" action="/uaa/login" method="post">
<h2>please login</h2>
<label for="username">username:</label>
<input type="text" id="username" name="username" value="z">
<label for="password">password:</label>
<input type="password" id="password" name="password" value="1">
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
<button type="submit">sign in</button>
</form>
</body>
</html>
ui服务代码如下
application.yml
auth-server: http://localhost:9001/uaa
server:
address: 127.0.0.1
port: 9002
context-path: /ui
spring:
redis:
host: 192.168.1.190
freemarker:
suffix: .html
cache: false
security:
basic:
enabled: false
oauth2:
client:
client-id: app
client-secret: 1
scope: openid
access-token-uri: ${auth-server}/oauth/token
user-authorization-uri: ${auth-server}/oauth/authorize
resource:
token-info-uri: ${auth-server}/oauth/check_token
AppUi.java
@SpringBootApplication
@EnableOAuth2Sso
@EnableRedisHttpSession
public class AppUi {
public static void main(String[] args) {
SpringApplication.run(AppUi.class, args);
}
@RequestMapping("/hello")
public String index(HttpSession session) {
return "hello";
}
}
两个服务引入的包如下
build.gradle
buildscript {
ext {
springBootVersion = '1.4.0.RELEASE'
}
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}
apply plugin: 'java'
apply plugin: 'idea'
apply plugin: 'eclipse'
apply plugin: 'spring-boot'
sourceCompatibility = 1.8
targetCompatibility = 1.8
repositories {
mavenCentral()
maven { url "https://repo.spring.io/snapshot" }
maven { url "https://repo.spring.io/milestone" }
}
dependencies {
compile 'org.springframework.boot:spring-boot-starter-security'
compile('org.springframework.boot:spring-boot-starter-freemarker')
compile('org.springframework.boot:spring-boot-starter-web')
compile("org.springframework.boot:spring-boot-devtools")
compile 'org.springframework.security.oauth:spring-security-oauth2'
compile 'org.springframework.session:spring-session-data-redis'
testCompile('org.springframework.boot:spring-boot-starter-test')
}
dependencyManagement {
imports {
mavenBom "org.springframework.cloud:spring-cloud-dependencies:Brixton.SR4"
}
}
eclipse {
classpath {
containers.remove('org.eclipse.jdt.launching.JRE_CONTAINER')
containers 'org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8'
}
}
解决方案
我今天用spring session用redis来持久化oauth2 server和client的会话,也出现了这个bug。
找了一个早上,根据Dave Syer和众人讨论的结果,我个人理解是spring core底层的DefaulListableBeanFactory
的serializationId
默认没有指定,spring session在用redis持久化session的时候把DefaulListableBeanFactory
也序列化进去,导致反序列的时候出现两个DefaulListableBeanFactory
的情况。
这个问题已经在spring core列为bug,4.3.10后面会修复....不过现在貌似还没出来
在讨论页面下面,Dave Syer给出了临时的解决方案,通过自定义的BeanFactoryPostProcessor
来确保各服务端的DefaulListableBeanFactory的serializationId
保持一致
private static final String SERIALIZATION_ID = "4086d293-522c-4d25-8485-f1c1f5c09218";
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
if ((beanFactory instanceof DefaultListableBeanFactory)) {
DefaultListableBeanFactory dlbf = (DefaultListableBeanFactory) beanFactory;
dlbf.setSerializationId(SERIALIZATION_ID);
}
}
这个问题就解决了
这篇关于spring-security - spring security oauth + redis session,客户端登录时author服务报错的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文