SpringSession系统对接CAS遇到的反序列化问题

SpringSession系统对接CAS遇到的反序列化问题

1、业务背景

业务背景:最近在对接CAS单点登录,遇到一个问题,加班到凌晨,先描述一下背景,首先公司的系统是基于Spring Session做的单点登录,目的是引用Spring Session实现会话共享,然后最近接到需求,要对接另外一个公司的CAS单点登录系统,也就是说自己公司内部多个子系统直接通过Spring session实现单点登录,然后再对接一个第三方公司的单点登录,听起来有点像非常规操作。

这个对接也就是自己的spring Session体系的系统作为一个cas client主体,然后再去对接CAS
在这里插入图片描述

2、单点登录

单点登录(Single sign on),英文名称缩写SSO,SSO的意思就是在多系统的环境中,登录单方系统,就可以在不用再次登录的情况下访问相关受信任的系统。也就是说只要登录一次单体系统就可以。

3、CAS单点登录

CAS(Center Authentication Service)是耶鲁大学研究的一款开源的单点登录项目,主要为web项目提供单点登录实现,属于Web SSO。然后,需要先了解CAS单点登录,按照CAS的规范进行对接,cas的资料可以参考我之前的:CAS单点登录系列博客

CAS官网资料:

CAS体系结构分为CAS Server和CAS Client。

CAS Server就是Cas开源的,需要去github下载,然后进行修改;Cas Client
可以是App或者web端的或者PC端,CAS支持多种开发语言,java、php、C#等等

这里写图片描述
PS:图来自官网,这里简单介绍一下,从图可以看出,CAS支持多种方式的认证,一种是LDAP的、比较常见的数据库Database的JDBC,还有Active Directory等等;支持的协议有Custom Protocol 、 CAS 、 OAuth 、 OpenID 、 RESTful API 、 SAML1.1 、 SAML2.0 等

下面给出一张来自CAS官方的图片
这里写图片描述
CAS登录等系统分为CAS Server和CAS Client,下面,我根据我的理解稍微解释一下:

1、用户访问CAS Client请求资源

2、客户端程序做了重定向,重定向到CAS Server

3、CAS Server会对请求做认证,验证是否有TGC(Ticket Granted Cookie,有TGC说明已经登录过,不需要再登录,没有就返回登录页面

4、认证通过后会生成一个Service Ticket返回Cas Client,客户端进行Ticket缓存,一般放在Cookie里,我们称之为TGC(Ticket Granted Cookie)

5、然后Cas Client就带着Ticket再次访问Cas Server,CAS Server进行Ticket验证

6、CAS Server对Ticket进行验证,通过就返回用户信息,用户拿到信息后就可以登录

4、原因分析

所以可以先分析一下怎么实现?首先既然是不同公司的登录系统,一般都会有两套的用户体系,所以可以先设计一张用户的关联表,然后两套系统的用户关联关系。按照CAS规范对接之后,我们拿到cas的登录用户账号,从关联表拿出公司系统(基于Spring Session)的用户账号,进行自己内部系统的登录

ok,看起来方案还是比较清晰,不过在上线后,出现麻烦的问题,就是自己的登录包登录之后,登录包拿到cas的用户之后,再取关联用户数据去进行内部系统的springSession单点登录之后,这个包是正常,不过在其它war包系统进行登录,发现,springsession,session对象都获取不到,一直抛异常,redis序列化失败,ClassNotFoundException?

org.springframework.data.redis.serializer.SerializationException: Cannot deseria
lize; nested exception is org.springframework.core.serializer.support.Serializat
ionFailedException: Failed to deserialize payload. Is the byte array a result of
corresponding serialization for DefaultDeserializer?; nested exception is org.s
pringframework.core.NestedIOException: Failed to deserialize object type; nested
exception is java.lang.ClassNotFoundException: org.jasig.cas.client.validation.
AssertionImpl
at org.springframework.data.redis.serializer.JdkSerializationRedisSerial
izer.deserialize(JdkSerializationRedisSerializer.java:41)
at org.springframework.data.redis.core.AbstractOperations.deserializeHas
hValue(AbstractOperations.java:316)
at org.springframework.data.redis.core.AbstractOperations.deserializeHas
hMap(AbstractOperations.java:277)
at org.springframework.data.redis.core.DefaultHashOperations.entries(Def
aultHashOperations.java:227)
at org.springframework.data.redis.core.DefaultBoundHashOperations.entrie
s(DefaultBoundHashOperations.java:101)

然后纠结想了很久,没找到原因,后来部门老大找到方法,就是在tomcat lib下面丢一下cas-client-core.jar

原因是什么?首先要对Spring session有一定了解,非spring session项目,Session的管理一般是给中间件,比如tomcat、weblogic等等进行管理的,而引用SpringSession项目后,Session管理给框架实现,然后会将数据同步到redis,也就是我们使用了setSession,数据都会同步到redis

同时,我们也要熟悉CAS,可以找cas client源码里找到如下代码:代码里将一个对象丢到里Session里
在这里插入图片描述

所以,就可以知道在知道原因了,我们分析一下:在对接CAS时,在过滤器里,我们将AssertionImpl这个对象丢到了Session里,然后经过springSession管理的项目,就有问题,可以先在cas源码里找到哪里进行了setSession

org.jasig.cas.client.jaas.Servlet3AuthenticationFilter
在这里插入图片描述
org.jasig.cas.client.validation.AbstractTicketValidationFilter.java:
在这里插入图片描述
ok,本博客进行比较浅显的分析,先做好记录,日后有时间再看看源码实现

5、附录资料

CAS官网资料:

文章来源: smilenicky.blog.csdn.net,作者:smileNicky,版权归原作者所有,如需转载,请联系作者。

原文链接:smilenicky.blog.csdn.net/article/details/118603415

(完)