【问题标题】:JJWT / Jackson alter the ObjectMapper usedJJWT / Jackson 更改使用的 ObjectMapper
【发布时间】:2018-09-23 12:50:36
【问题描述】:

对于我正在进行的项目,我需要使用库 io.jsonwebtoken (jjwt) 提供的 Spring Security 和 JSON Webtokens。我需要添加到生成的令牌中的声明之一是以下实体(简化以说明问题):

@Entity
public class MyEntity {
    private String name;
    private LocalDateTime ldt;
}

这可行,但生成的 webtoken 序列化如下:

{
  "sub": "testuser@mydomain.com",
  "exp": 1523659655,
  "entity": {
    "name": testname,
    "ldt": {
      "hour": 0,
      "minute": 37,
      "dayOfMonth": 12,
      "dayOfWeek": "THURSDAY",
      "dayOfYear": 102,
      "year": 2018,
      "month": "APRIL",
      "monthValue": 4,
      "second": 38,
      "nano": 569000000,
      "chronology": {
        "calendarType": "iso8601",
        "id": "ISO"
      }
    }
  }
}

这看起来可能不是问题,但实际上当我需要再次将它映射到 MyEntity 的实例时,它实际上是一个问题。在线阅读后,我想我需要更改 ObjectMapper 的配置,以更改配置选项(将WRITE_DATES_AS_TIMESTAMPS-flag 切换为 false)。但是,我无法更改 jjwt 使用的 ObjectMapper 的配置,因为它是这样构造的(jjwt 的来源):

public class DefaultJwtBuilder implements JwtBuilder {
    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
    ...
}

我在网上找到的另一个选择是将以下行放在我的 application.properties 文件中:

spring.jackson.serialization.WRITE_DATES_AS_TIMESTAMPS = false

然而无济于事,jjwt使用的ObjectMapper似乎忽略了这些属性。

我会做些什么来实现我的目标?

【问题讨论】:

    标签: java spring jackson2 jsr310 jjwt


    【解决方案1】:

    我通过覆盖 DefaultJwtBuilder 来修复它,如下所示:

    public class CustomJwtBuilder extends DefaultJwtBuilder {
        private static final ObjectMapper mapper = new Jackson2ObjectMapperBuilder()
            .featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
            .modulesToInstall(new JavaTimeModule())
            .build();
    
        @Override
        protected byte[] toJson(Object object) throws JsonProcessingException {
            return mapper.writeValueAsBytes(object);
        }
    }
    

    然后像这样创建令牌

    String token = new CustomJwtBuilder()
                .setSubject(..)
                .setExpiration(...)
                .compact();
    

    【讨论】:

    • 我知道这个答案是在 JJWT 0.10.0 发布之前提供的,但是在 0.10.0 之后,tete 在这个页面上的答案是推荐的解决方案。 JJWT 用户应该关注那个。干杯!
    • @LesHazlewood 我已经接受了这个答案;我最初问这个问题时还不可能。
    • 我知道,我说“我知道这个答案是在 JJWT 0.10.0 发布之前提供的”:)。但感谢您更新答案! ;)
    【解决方案2】:

    Jjwt 文档指出(从 0.10.0 及更高版本开始)您可以注入您自己的具有特定编译依赖项的 ObjectMapper,并按如下方式实现注入:

    <dependency>
        <groupId>io.jsonwebtoken</groupId>
        <artifactId>jjwt-jackson</artifactId>
        <version>0.10.5</version>
        <scope>compile</scope> <!-- Not runtime -->
    </dependency>
    

    ...然后将映射器添加到JwtBuilder:

    ObjectMapper objectMapper = getMyObjectMapper(); //implement me
    String jws = Jwts.builder()
        .serializeToJsonWith(new JacksonSerializer(objectMapper))
        // ... etc ...
    

    作为documented here

    【讨论】:

    • 对于那些想知道如何实现getMyObjectMapper() 的人,这取决于您如何管理依赖注入。如果您使用的是普通的旧 Java,return new ObjectMapper(); 就可以(使用所需的配置);如果您使用的是 Spring,那么该方法可能会返回一个自动装配的实例。这超出了这个问题的重点。
    【解决方案3】:

    通常当编译器无法在类路径上发现任何 JSON 序列化器实现时会发生这种情况。包括以下 jjwt jackson 依赖并重建项目。它解决了我的问题。

    <dependency>
        <groupId>io.jsonwebtoken</groupId>
        <artifactId>jjwt-jackson</artifactId>
        <version>0.10.5</version>
        <scope>compile</scope>
    </dependency>
    

    【讨论】:

      猜你喜欢
      • 2018-07-09
      • 2012-02-19
      • 2019-01-28
      • 2014-05-06
      • 2019-04-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-01
      相关资源
      最近更新 更多