我正在实现一个RESTful Web服务,用户必须发送一个签名的验证令牌以及请求,这样我才能确保请求没有被中间人篡改.我目前的实施如下.
验证令牌是序列化为String的VerifData对象,然后进行散列和加密.
class VerifData { int prop1; int prop2; }
在我的服务中,我将要序列化的数据放入VerifData实例中,然后使用Jackson ObjectMapper对其进行序列化,并将其与验证令牌一起传递给验证引擎.
VerfiData verifData = new VerifData(12345, 67890); ObjectMapper mapper = new ObjectMapper(); String verifCodeGenerated = mapper.writeValueAsString(verifData);
但似乎每次启动应用程序容器时,ObjectMapper映射到字符串的属性顺序都会发生变化.
例如:有一次
{"prop1":12345,"prop2":67890}
它将是另一次
{"prop2":67890,"prop1":12345}
因此,如果客户端已将VerifData实例序列化为第一个String,则即使它是正确的,也有50%的可能性失败.
有办法解决这个问题吗?我可以通过ObjectMapper指定要映射的属性的顺序(如升序)吗?或者是否有其他方法可以最好地实施此验证步骤.客户端和服务器实现都是由我开发的.我使用Java Security API进行签名和验证.
注释很有用,但在任何地方都可以使用.您可以将整个ObjectMapper配置为以这种方式工作
目前杰克逊版本:
objectMapper.configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, true)
老杰克逊版本:
objectMapper.configure(SerializationConfig.Feature.SORT_PROPERTIES_ALPHABETICALLY, true);
在Spring Boot中,您可以通过将以下内容添加到Application
入口点类来全局添加此行为:
@Bean public Jackson2ObjectMapperBuilder objectMapperBuilder() { Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder(); builder.featuresToEnable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY); return builder; }
通过指定属性,在Spring Boot中有一种更简单的方法(application.properties
例如:
spring.jackson.mapper.sort_properties_alphabetically=true
来自Jackson Annotations文档:
// ensure that "id" and "name" are output before other properties @JsonPropertyOrder({ "id", "name" }) // order any properties that don't have explicit setting using alphabetic order @JsonPropertyOrder(alphabetic=true)