Part 7: what readValue(json, Object.class) actually does on a default mapper
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
package com.ankurm.jackson3.part7security;
|
||||
|
||||
import tools.jackson.databind.json.JsonMapper;
|
||||
|
||||
/**
|
||||
* Post: Jackson Security Best Practices — https://ankurm.com/jackson-security-best-practices/
|
||||
* Section: "Never Deserialise Untrusted JSON into Object.class"
|
||||
*
|
||||
* Worth knowing precisely what readValue(json, Object.class) does on a DEFAULT
|
||||
* Jackson 3 mapper, because the answer is reassuring and often misunderstood:
|
||||
* with no default typing active it produces plain Maps, Lists, Strings and numbers.
|
||||
* The danger only returns when default typing is switched on — as H03 shows.
|
||||
*
|
||||
* The rule still stands. Target a specific type; you get validation for free.
|
||||
*/
|
||||
public class H05NeverDeserialiseIntoObject {
|
||||
|
||||
public record MyRequestDto(String action, int quantity) { }
|
||||
|
||||
public static void main(String[] args) {
|
||||
JsonMapper mapper = JsonMapper.builder().build();
|
||||
|
||||
String untrusted = "{\"action\":\"ship\",\"quantity\":3,\"extra\":{\"nested\":[1,2]}}";
|
||||
|
||||
Object loose = mapper.readValue(untrusted, Object.class);
|
||||
System.out.println("as Object : " + loose);
|
||||
System.out.println("runtime type: " + loose.getClass().getName()
|
||||
+ " <- a plain Map, no arbitrary class was instantiated");
|
||||
|
||||
MyRequestDto typed = mapper.readValue(untrusted, MyRequestDto.class);
|
||||
System.out.println("as DTO : " + typed);
|
||||
|
||||
// The real benefit of a specific target type: malformed input fails loudly
|
||||
// instead of flowing onward as an untyped Map.
|
||||
try {
|
||||
mapper.readValue("{\"action\":\"ship\",\"quantity\":\"not-a-number\"}", MyRequestDto.class);
|
||||
System.out.println("bad input : UNEXPECTEDLY ACCEPTED");
|
||||
} catch (Exception e) {
|
||||
System.out.println("bad input : rejected with " + e.getClass().getSimpleName());
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user