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

Spring Boot集成OAuth2遇Java 8日期序列化错误求解决方案

解决Spring Boot OAuth2 SSO中Jackson无法序列化Java 8 Instant类型的问题

问题背景

基于Spring Boot + OAuth2实现SSO,引入第三方SSO提供商的依赖包后,出现Jackson序列化错误:无法处理java.time.Instant类型(具体是OidcUserAuthority属性中的auth_time字段)。已确认项目包含jackson-datatype-jsr310依赖,且升级过Jackson库,但问题未解决。

修复方案

1. 手动注册Jackson Java 8日期模块

依赖存在但Spring未自动注册模块时,需手动配置ObjectMapper:

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;

@Configuration
public class JacksonConfig {
    @Bean
    public ObjectMapper objectMapper(Jackson2ObjectMapperBuilder builder) {
        ObjectMapper objectMapper = builder.build();
        // 注册Java 8日期时间处理模块
        objectMapper.registerModule(new JavaTimeModule());
        // 可选:关闭时间戳序列化,转为ISO格式字符串
        objectMapper.configure(com.fasterxml.jackson.databind.SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
        return objectMapper;
    }
}

2. 预处理OIDC用户权限中的Instant字段

在返回包含OidcUserAuthority的用户信息前,手动将auth_time字段转换为可序列化类型:

import org.springframework.security.oauth2.core.oidc.user.OidcUser;
import org.springframework.security.oauth2.core.oidc.user.OidcUserAuthority;
import java.time.Instant;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;

// 在获取并返回用户信息的逻辑中添加处理
public Map<String, Object> buildUserResponse(OidcUser oidcUser) {
    Map<String, Object> response = new HashMap<>(oidcUser.getClaims());
    
    // 处理权限集合中的auth_time字段
    response.put("roles", oidcUser.getAuthorities().stream()
            .map(auth -> {
                if (auth instanceof OidcUserAuthority) {
                    OidcUserAuthority oidcAuth = (OidcUserAuthority) auth;
                    Map<String, Object> attrs = new HashMap<>(oidcAuth.getAttributes());
                    // 将Instant转为ISO标准字符串
                    if (attrs.containsKey("auth_time")) {
                        attrs.put("auth_time", ((Instant) attrs.get("auth_time")).toString());
                    }
                    return attrs;
                }
                return auth.getAuthority();
            })
            .collect(Collectors.toSet()));
    
    return response;
}

3. 排查并解决Jackson依赖冲突

不同版本的Jackson组件可能导致模块无法正常工作,通过依赖树命令检查版本一致性:

  • Maven:执行 mvn dependency:tree
  • Gradle:执行 ./gradlew dependencies

若存在版本不一致,在依赖管理中强制统一版本(以Maven为例):

<properties>
    <jackson.version>2.15.2</jackson.version>
</properties>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>${jackson.version}</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>${jackson.version}</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.datatype</groupId>
            <artifactId>jackson-datatype-jsr310</artifactId>
            <version>${jackson.version}</version>
        </dependency>
    </dependencies>
</dependencyManagement>

4. 自定义Jackson消息转换器

确保Spring MVC使用配置好的ObjectMapper,手动替换默认消息转换器:

import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.util.List;

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    private final ObjectMapper objectMapper;

    public WebMvcConfig(ObjectMapper objectMapper) {
        this.objectMapper = objectMapper;
    }

    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
        converter.setObjectMapper(objectMapper);
        converters.add(0, converter); // 设置为优先使用的转换器
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 03:53:15