游乐游手机版
首页/数据库/文章详情

Security整合Redis为何序列化报错_配专用反序列化器

时间:2026-04-24 20:27
Security对象反序列化必报错,因Spring Security内置类无无参构造器且Jackson默认不识别;需配置ObjectMapper开启DefaultTyping、可见性,并注册SimpleGrantedAuthorityDeserializer和UsernamePasswordAuth

Security对象反序列化必报错,因Spring Security内置类无无参构造器且Jackson默认不识别;需配置ObjectMapper开启DefaultTyping、可见性,并注册SimpleGrantedAuthorityDeserializer和UsernamePasswordAuthenticationToken MixIn。

Security整合Redis为何序列化报错_配专用反序列化器

把Security对象存进Redis后取不出来,这事儿太常见了。问题往往不是配置漏了,而是反序列化器没对上类型——尤其是像 SimpleGrantedAuthorityUsernamePasswordAuthenticationToken 这类Spring Security框架的内置类,Jackson默认根本不认识它们。

为什么 Security 对象反序列化必报错

Spring Security的认证对象(比如 AuthenticationSecurityContext)在设计上就和标准POJO不太一样。它们大多没有无参构造器,身上也没贴 @JsonCreator 注解。Jackson默认只认规规矩矩的POJO,一碰到这些“特立独行”的类,处理方式就很简单粗暴:直接退化成 LinkedHashMap。结果呢?最后抛出那个经典的 ClassCastException: LinkedHashMap cannot be cast to SecurityContext。更棘手的是 SimpleGrantedAuthority,它的构造参数虽然只是个 String,但在JSON序列化后,可能变成一个带了 @class 字段的复杂结构,反序列化时自然找不到匹配的构造器。

必须配 ObjectMapper + DefaultTyping

光用一个 Jackson2JsonRedisSerializer 是远远不够的,关键得让它“认识”并记住这些对象的运行时类型信息。这就必须对底层的 ObjectMapper 进行精准配置:

  • objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL) —— 这是核心,让所有非final类在序列化时自动带上 @class 字段,记录类型。
  • objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY) —— 放宽可见性规则,允许Jackson访问私有字段和getter方法。
  • 最后,也是最容易漏掉的一步:必须调用 jsonSerializer.setObjectMapper(objectMapper),否则上面的配置全是白费功夫。

这三条,漏掉任意一条,反序列化都会在类型还原的关键阶段失败。

自定义 SimpleGrantedAuthorityDeserializer 是刚需

即便开了 DefaultTypingSimpleGrantedAuthority 这个类因为其特殊的构造方式,仍然可能反序列化失败。这时候,一个专用的反序列化器就成了必需品:

public class SimpleGrantedAuthorityDeserializer extends StdDeserializer {
    public SimpleGrantedAuthorityDeserializer() {
        super(SimpleGrantedAuthority.class);
    }

    @Override
    public SimpleGrantedAuthority deserialize(JsonParser p, DeserializationContext ctxt)
            throws IOException {
        JsonNode node = p.getCodec().readTree(p);
        String authority = node.has("authority") ? node.get("authority").asText() : node.asText();
        return new SimpleGrantedAuthority(authority);
    }
}

写好之后,别忘了把它注册到 ObjectMapper 里:

  • SimpleModule module = new SimpleModule();
  • module.addDeserializer(SimpleGrantedAuthority.class, new SimpleGrantedAuthorityDeserializer());
  • objectMapper.registerModule(module);

别忽略 UsernamePasswordAuthenticationToken 的构造约束

这个类的情况又有所不同。它只有带参构造器,并且参数顺序是固定的(principal, credentials, authorities)。Jackson需要明确知道如何传递这些参数,否则就会报 Cannot construct instance... no Creators 的错误。通常有两种应对策略:

  • 第一种,给你自己的子类加上 @JsonCreator@JsonProperty 注解。但这种方式不推荐,因为修改框架类或其子类会带来侵入性。
  • 第二种,也是更优雅安全的方式:使用MixIn。具体操作是,新建一个空的 UsernamePasswordAuthenticationTokenMixin 类,在里面通过 @JsonCreator(mode = JsonCreator.Mode.PROPERTIES) 和对应的 @JsonProperty 注解来定义反序列化规则。然后通过 objectMapper.addMixIn(UsernamePasswordAuthenticationToken.class, UsernamePasswordAuthenticationTokenMixin.class) 进行绑定。这种方式无侵入,也避免了直接开启 AutoTypeSupport(true) 可能带来的反序列化安全风险。

话说回来,真正让人卡住的地方,往往不是“知不知道要配”,而是配置了却没生效。比如,ObjectMapper 实例没真正挂载到序列化器上,或者MixIn的注册顺序错了——如果在 setObjectMapper 之后才注册模块,那这个模块压根就不会起作用。这些细节,才是解决问题的关键所在。

来源:https://www.php.cn/faq/2342064.html
上一篇SQL如何计算字段的平均值?AVG聚合函数数据统计 下一篇Oracle RMAN在生产环境备份需注意什么_配置备份排除策略
本站内容用于信息整理与展示,如有侵权或内容问题请及时联系处理。

相关推荐

补充同频道和同主题内容,方便继续浏览更多相关内容。

同类最新

继续查看同栏目最近更新的文章。

更多
金仓数据库逻辑备份实战:全库导出与模式替换全流程
数据库 · 2026-07-03

金仓数据库逻辑备份实战:全库导出与模式替换全流程

在长期的运维实践中,我越来越体会到,备份就像一份保险——平时看似无用,但关键时刻却是唯一的救命稻草。逻辑备份看似简单,可真正执行恢复时,各种陷阱接连浮现:表名大小写不一致、Schema 未正确切换、Owner 属性未同步修改……任何一个环节处理不当,最终恢复出的数据库就会与预期相去甚远。 本文将深入

金仓数据库sys_rman物理备份全流程演练与误覆盖恢复
数据库 · 2026-07-03

金仓数据库sys_rman物理备份全流程演练与误覆盖恢复

干运维这行,逻辑备份和物理备份我都接触过,但说句实在话,真正能在生产环境里扛住事儿的,还得是物理备份。逻辑备份导出的是 SQL 语句,数据量一大,那速度慢得让人抓狂,而且最关键的是,它没法做时间点恢复。物理备份不一样,它直接拷贝数据文件,再配上 WAL 归档日志,想恢复到过去哪一秒都行,这是它最硬核

Windows下将MySQL注册为系统自启服务教程
数据库 · 2026-07-03

Windows下将MySQL注册为系统自启服务教程

先说一个关键前提:务必以管理员身份运行终端,否则 mysqld --install 这条命令几乎不可能成功。问题不在于命令写错,而是 Windows 系统的用户账户控制(UAC)机制会在中途拦截——在普通 CMD 或 PowerShell 窗口执行这条命令,要么直接提示 Access is deni

Mac版Navicat中快速对比两个数据库的表结构异同
数据库 · 2026-07-03

Mac版Navicat中快速对比两个数据库的表结构异同

直接说结论:Mac 版 Navicat 和 Windows 版在表结构比对逻辑上完全一致。但默认配置下,它确实无法承受“全库一键比对上万张表”的压力。要想避免卡死、内存溢出、进度条永远停在 0%,你必须手动将表分批处理,或者利用前缀过滤来控制扫描范围。 为什么 Mac 上点击「结构同步」后界面会卡住

MySQL中UNION操作推荐用UNION ALL的原因
数据库 · 2026-07-03

MySQL中UNION操作推荐用UNION ALL的原因

MySQL中UNION与UNION ALL性能对比:别再被“保险”迷惑,差距远超预期 先给出核心结论:UNION ALL 的性能通常比 UNION 高出不止一个数量级。原因在于,UNION 在合并结果集后会自动触发去重操作,这往往伴随着隐式排序,进而产生临时表和文件排序。而 UNION ALL 则直