我正在实施一个RESTful Web服务,用户必须在其中发送已签名的验证令牌以及请求,这样我才能确保请求未被中间人篡改。我目前的实施如下。
Verification令牌是一个VerifData对象,序列化为String,然后进行散列和加密。
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映射到字符串的属性顺序都会发生变化。
Ex:有一次会是
{"prop1":12345,"prop2":67890}
另一次是
{"prop2":67890,"prop1":12345}
因此,如果客户端已将VerifData实例序列化为第一个String,则即使它是正确的,也有50%的可能性失败。
有没有办法解决这个问题?我可以通过ObjectMapper指定要映射的属性的顺序(如升序)吗?或者是否有其他方法可以最好地实施此验证步骤。客户端和服务器实现都是由我开发的。我使用Java Security API进行签名和验证。
答案 0 :(得分:65)
注释很有用,但在任何地方都可以使用。您可以使用
配置整个ObjectMapper以这种方式工作目前杰克逊版本:
objectMapper.configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, true)
旧杰克逊版本:
objectMapper.configure(SerializationConfig.Feature.SORT_PROPERTIES_ALPHABETICALLY, true);
答案 1 :(得分:61)
来自Jackson Annotations documentation:
// 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)
答案 2 :(得分:9)
在Spring Boot中,您可以通过将以下内容添加到Application
入口点类来全局添加此行为:
@Bean
public Jackson2ObjectMapperBuilder objectMapperBuilder() {
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
builder.featuresToEnable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY);
return builder;
}
答案 3 :(得分:8)
通过指定属性,在Spring Boot中有一种更简单的方法(例如在application.properties
中:
spring.jackson.mapper.sort_properties_alphabetically=true
答案 4 :(得分:7)
需要以下 2 ObjectMapper配置:
ObjectMapper.configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, true)
或
ObjectMapper.enable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY)
定义用于POJO字段的属性序列化顺序
注意:不是适用于java.util.Map
序列化!
和
ObjectMapper.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true)
或
ObjectMapper.enable(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS)
确定
java.util.Map
条目是否在序列化之前首先按键按进行排序的功能
Spring Boot配置示例(yaml):
spring:
jackson:
mapper:
SORT_PROPERTIES_ALPHABETICALLY: true
serialization:
ORDER_MAP_ENTRIES_BY_KEYS: true
答案 5 :(得分:4)
来自Duncan McGregor的回答: 最好像这样使用它:
objectMapper.configure(SerializationConfig.Feature.SORT_PROPERTIES_ALPHABETICALLY, true);
MapperFeature用于XML,并附带jackson-databind,这不是必需的......
答案 6 :(得分:2)
在你今天可能使用的Jackson 2.x中,使用:
ObjectMapper mapper = new ObjectMapper();
mapper.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true);
如果你关心外表,你也可以考虑SerializationFeature.INDENT_OUTPUT
。
请注意,您必须序列化地图或对象才能正确排序。如果您序列化JsonNode
例如(来自readTree
),则无法正确缩进。
import com.fasterxml.jackson.databind.*;
ObjectMapper mapper = new ObjectMapper();
mapper.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true);
mapper.configure(SerializationFeature.INDENT_OUTPUT, true);
String input = "{\"hello\": {\"cruel\" : \"world\"} }";
Object pojo = mapper.readValue(input, Object.class);
System.out.println(mapper.writeValueAsString(pojo));
结果:
{
"hello" : {
"cruel" : "world"
}
}
答案 7 :(得分:1)
我今天发现了另一种方法,以防字母不是您想要的排序顺序。事实证明,如果其余字段未注释,则在字段上添加 @JsonProperty 注释会在写入时将其放在最后。我发现当我想指定一个不符合java命名约定的属性名称时。
通过添加索引属性,您可以定义顺序。最低的索引放在最前面。
@JsonProperty(index=20)
String prop1;
@JsonProperty(index=10)
String prop2;
将呈现:
{"prop2": "valueProp2", "prop1": "valueProp1"}
答案 8 :(得分:0)
代替使用flag参数:
objectMapper.enable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY);
答案 9 :(得分:0)
您可以使用混入并根据需要指定属性的顺序:
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
@Component
public final class ObjectMapperUtils {
private static final ObjectMapper MAPPER = new ObjectMapper();
static {
MAPPER.addMixIn(Object.class, IdFirst.class);
}
@Bean
public ObjectMapper objectMapper() {
return MAPPER;
}
@JsonPropertyOrder({"id", "...", "..."})
private abstract static class IdFirst {}
}
答案 10 :(得分:0)
我意识到这是一个老话题,但是由于我一直在寻找或回答并着陆于此,因此一些其他信息可能对其他人很方便。
我当前正在使用的@JsonProperty批注(jackson-annotations-2.11.2)接受“ value”参数之外的“ index”(数字)参数,该参数指定序列化期间字段的顺序。