Estoy implementando un servicio web RESTful en donde el usuario tiene que enviar una firma de verificación de token junto con la solicitud para que yo pudiera asegurarse de que la solicitud no ha sido alterado por un hombre medio. Mi aplicación actual es la siguiente.

De verificación de token es un VerifData objeto serializado en una Cadena y, a continuación, hash y cifrados.

class VerifData {
    int prop1;
    int prop2;
}

En mi servicio, me puse de datos a serializarse en una instancia de VerifData y, a continuación, serializar el uso de Jackson ObjectMapper y pasa a lo largo de la verificación del motor junto con la verificación de token.

VerfiData verifData = new VerifData(12345, 67890);
ObjectMapper mapper = new ObjectMapper();
String verifCodeGenerated = mapper.writeValueAsString(verifData);

Pero parece que cada vez que el contenedor de aplicación se inicia, el orden de las propiedades que se asignan en una cadena ObjectMapper cambios.

Ex: una vez

{"prop1":12345,"prop2":67890}

y otra vez que sería

{"prop2":67890,"prop1":12345}

Así que si el cliente ha serializado la VerifData instancia como en la primera Cadena, hay un 50% de probabilidad de error, incluso a pesar de que es correcta.

Es allí una manera de conseguir alrededor de esto? Puede especificar el orden de las propiedades de mapa por ObjectMapper (como en orden ascendente)? O hay alguna otra forma mejor manera de implementar este paso de verificación. Tanto el cliente como el servidor implementaciones son desarrollados por mí. Yo uso la Seguridad de Java API para la firma y verificación.

InformationsquelleAutor Lihini | 2014-12-20

7 Comentarios

  1. 64

    De la Jackson Anotaciones documentación:

    //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)
    • desde el enlace «todos los codehaus servicios han terminado»
    • thx. actualizado el enlace
    • Como se menciona a continuación, si su meta es aplicar el orden en todas partes en lugar de al serializar un objeto específico, consulte stackoverflow.com/a/46267506/2089674.
  2. 69

    Las anotaciones son útiles, pero puede ser un dolor para aplicar en todas partes. Usted puede configurar su conjunto ObjectMapper a trabajar de esta manera con

    Actual Jackson versiones:
    objectMapper.configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, true)

    Mayores Jackson versiones:
    objectMapper.configure(SerializationConfig.Feature.SORT_PROPERTIES_ALPHABETICALLY, true);

    • Esto funcionó para mí… el uso de jackson 2.7.1. Gracias
    • Esto no funciona en 2.7.4
    • En versiones posteriores se debe usar .configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, true)
    • Esto no es del todo correcto (o al menos no funciona en todos los escenarios) — vea stackoverflow.com/a/46267506/2089674 para ver un ejemplo completo de algo que funciona.
    • su ejemplo sólo funciona para asignar teclas. El OP pidió una solución para los campos de Objeto.
  3. 9

    En la Primavera de Inicio puede agregar este comportamiento a nivel mundial mediante la adición de la siguiente Application punto de entrada de la clase:

      @Bean
      public Jackson2ObjectMapperBuilder objectMapperBuilder() {
    
        Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
        builder.featuresToEnable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY);
    
        return builder;
      }
  4. 8

    Hay una forma más fácil en la Primavera de Arranque mediante la especificación de una propiedad (en application.properties por ejemplo:

    spring.jackson.mapper.sort_properties_alphabetically=true
    • Alguien puede confirmar que funciona?
    • Sí, funciona.
  5. 3

    De Duncan McGregor la respuesta:
    Su mejor uso es como este:

    objectMapper.configure(SerializationConfig.Feature.SORT_PROPERTIES_ALPHABETICALLY, true);

    como MapperFeature es para XMLs y viene con jackson-databind que no es necesario…

  6. 3

    En Jackson 2.x, que probablemente se está utilizando hoy en día, el uso de:

    ObjectMapper mapper = new ObjectMapper();
    mapper.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true);

    Si te preocupa ve, también se puede considerar SerializationFeature.INDENT_OUTPUT así.

    Tenga en cuenta que debe serializar Mapas o Objetos para que este ordene correctamente. Si se serializa un JsonNode por ejemplo (de readTree), que no se realizará correctamente sangría.

    Ejemplo

    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));

    resultados en:

    {
      "hello" : {
        "cruel" : "world"
      }
    }
    • Sólo hay una entrada de mapa. Por eso no puedo ver es el fin.
  7. 0

    Lugar de utilizar la bandera argumento:

    objectMapper.enable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY);

Dejar respuesta

Please enter your comment!
Please enter your name here