You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

CAS 7.0.2集成GitHub身份委托时TicketGrantingTicketImpl反序列化错误求助

CAS 7.0.2 GitHub委托认证Redis存储Ticket反序列化错误问题

问题描述

在CAS 7.0.2中配置GitHub作为委托身份提供商,账号授权流程可正常完成,但控制台持续抛出TicketGrantingTicketImpl反序列化错误(Ticket存储于Redis)。

错误日志

2024-03-26 15:05:02,752 ERROR 
[org.apereo.cas.util.serialization.AbstractJacksonBackedStringSerializer] - <Cannot read/parse [{"@class":"org.apereo.cas.ticket.TicketGrantingTicketImpl","@id":1,"id":"TGT-1-********qFm6SjQ17y...] to deserialize into type [class org.apereo.cas.ticket.TicketGrantingTicketImpl]. This may be caused in the absence of a configuration/support module that knows how to interpret the fragment, specially if the fragment describes a CAS registered service definition. Internal parsing error is [Cannot construct instance of `org.pac4j.oauth.credentials.OAuth20Credentials` (although at least one Creator exists): cannot deserialize from Object value (no delegate- or property-based Creator)
 at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); line: 1, column: 2090] (through reference chain: org.apereo.cas.ticket.TicketGrantingTicketImpl["authentication"]->org.apereo.cas.authentication.DefaultAuthentication["credentials"]->java.util.ArrayList[0]->org.apereo.cas.authentication.principal.ClientCredential["credentials"])]>
2024-03-26 15:05:02,758 ERROR [org.apereo.cas.ticket.registry.DefaultTicketRegistryCleaner] - <INVALID_TICKET
 DefaultTicketStringSerializationManager.java:deserializeTicket:60
 DefaultTicketStringSerializationManager.java:lambda$deserializeTicket$1:49
 Unchecked.java:lambda$supplier$38:1695
>
2024-03-26 15:05:52,249 INFO [org.apereo.cas.services.mgmt.AbstractServicesManager] - <Loaded [2] service(s) from [EmbeddedResourceBasedServiceRegistry].>
2024-03-26 15:06:35,242 ERROR [org.apereo.cas.util.serialization.AbstractJacksonBackedStringSerializer] - <Cannot read/parse [{"@class":"org.apereo.cas.ticket.TicketGrantingTicketImpl","@id":1,"id":"TGT-1-********qFm6SjQ17y...] to deserialize into type [class org.apereo.cas.ticket.TicketGrantingTicketImpl]. This may be caused in the absence of a configuration/support module that knows how to interpret the fragment, specially if the fragment describes a CAS registered service definition. Internal parsing error is [Cannot construct instance of `org.pac4j.oauth.credentials.OAuth20Credentials` (although at least one Creator exists): cannot deserialize from Object value (no delegate- or property-based Creator)
 at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); line: 1, column: 2090] (through reference chain: org.apereo.cas.ticket.TicketGrantingTicketImpl["authentication"]->org.apereo.cas.authentication.DefaultAuthentication["credentials"]->java.util.ArrayList[0]->org.apereo.cas.authentication.principal.ClientCredential["credentials"])]>
2024-03-26 15:06:35,342 ERROR [org.apereo.cas.util.serialization.AbstractJacksonBackedStringSerializer] - <Cannot read/parse [{"@class":"org.apereo.cas.ticket.TicketGrantingTicketImpl","@id":1,"id":"TGT-1-********qFm6SjQ17y...] to deserialize into type [class org.apereo.cas.ticket.TicketGrantingTicketImpl]. This may be caused in the absence of a configuration/support module that knows how to interpret the fragment, specially if the fragment describes a CAS registered service definition. Internal parsing error is [Cannot construct instance of `org.pac4j.oauth.credentials.OAuth20Credentials` (although at least one Creator exists): cannot deserialize from Object value (no delegate- or property-based Creator)
 at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); line: 1, column: 2090] (through reference chain: org.apereo.cas.ticket.TicketGrantingTicketImpl["authentication"]->org.apereo.cas.authentication.DefaultAuthentication["credentials"]->java.util.ArrayList[0]->org.apereo.cas.authentication.principal.ClientCredential["credentials"])]>
2024-03-26 15:06:35,353 ERROR [org.apereo.cas.util.serialization.AbstractJacksonBackedStringSerializer] - <Cannot read/parse [{"@class":"org.apereo.cas.ticket.TicketGrantingTicketImpl","@id":1,"id":"TGT-1-********qFm6SjQ17y...] to deserialize into type [class org.apereo.cas.ticket.TicketGrantingTicketImpl]. This may be caused in the absence of a configuration/support module that knows how to interpret the fragment, specially if the fragment describes a CAS registered service definition. Internal parsing error is [Cannot construct instance of `org.pac4j.oauth.credentials.OAuth20Credentials` (although at least one Creator exists): cannot deserialize from Object value (no delegate- or property-based Creator)
 at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); line: 1, column: 2090] (through reference chain: org.apereo.cas.ticket.TicketGrantingTicketImpl["authentication"]->org.apereo.cas.authentication.DefaultAuthentication["credentials"]->java.util.ArrayList[0]->org.apereo.cas.authentication.principal.ClientCredential["credentials"])]>
2024-03-26 15:06:52,256 INFO [org.apereo.cas.services.mgmt.AbstractServicesManager] - <Loaded [2] service(s) from [EmbeddedResourceBasedServiceRegistry].>

排查信息

  • org.pac4j.oauth.credentials.OAuth20Credentials类(来自org.pac4j.pac4j-oauth:6.0.0)默认无无参构造器
  • 该逻辑在CAS 6.6.0版本中可正常运行

当前GitHub委托认证配置

cas.authn.pac4j.github.id=xxx
cas.authn.pac4j.github.secret=xxx
cas.authn.pac4j.github.client-name=github
cas.authn.pac4j.github.callback-url=https://xxx.goho.co

解决方法

方法1:自定义Jackson模块支持OAuth20Credentials序列化/反序列化

创建自定义Jackson模块,为OAuth20Credentials类指定使用带参构造器完成反序列化:

import com.fasterxml.jackson.databind.module.SimpleModule;
import org.pac4j.oauth.credentials.OAuth20Credentials;
import com.fasterxml.jackson.databind.deser.BeanDeserializerModifier;
import com.fasterxml.jackson.databind.deser.ValueInstantiator;
import com.fasterxml.jackson.databind.deser.std.StdValueInstantiator;
import com.fasterxml.jackson.databind.introspect.AnnotatedClass;
import com.fasterxml.jackson.databind.introspect.AnnotatedConstructor;
import java.util.List;

public class Pac4jOAuth20CredentialsModule extends SimpleModule {
    public Pac4jOAuth20CredentialsModule() {
        super("Pac4jOAuth20CredentialsModule");
        setDeserializerModifier(new BeanDeserializerModifier() {
            @Override
            public ValueInstantiator modifyValueInstantiator(com.fasterxml.jackson.databind.DeserializationConfig config, AnnotatedClass ac, ValueInstantiator defaultInstantiator) {
                if (ac.getRawType() == OAuth20Credentials.class) {
                    List<AnnotatedConstructor> constructors = ac.getConstructors();
                    for (AnnotatedConstructor ctor : constructors) {
                        // 匹配OAuth20Credentials的带参构造器(参数为code, token, clientName)
                        if (ctor.getParameterCount() == 3) {
                            return new StdValueInstantiator(config, ac) {
                                @Override
                                public boolean canCreateFromObjectWith() {
                                    return true;
                                }
                            };
                        }
                    }
                }
                return defaultInstantiator;
            }
        });
    }
}

将该模块注册到CAS的Spring上下文:

@Bean
public Module pac4jOAuth20CredentialsModule() {
    return new Pac4jOAuth20CredentialsModule();
}

方法2:修改Ticket序列化策略,排除凭证字段

在CAS配置文件中添加配置,让Redis存储Ticket时忽略无法反序列化的凭证字段:

# 排除整个credentials列表
cas.ticket.registry.redis.serialization.exclude-fields=authentication.credentials
# 或精准排除嵌套的OAuth20Credentials
cas.ticket.registry.redis.serialization.exclude-fields=authentication.credentials[0].credentials

此方法会丢失凭证信息,适合无需回溯凭证的业务场景。

方法3:统一pac4j依赖版本

检查CAS 7.0.2官方依赖管理中指定的pac4j版本,确保项目中pac4j-oauth的版本与CAS官方推荐版本一致,避免版本不兼容导致的序列化问题。


内容的提问来源于stack exchange,提问作者Beer Gold

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 21:48:15