# 프로파일이 선언하는 세 상한 * @param maxDepth deepest accepted nesting * @param maxArrayElements most elements accepted in one array * @param maxStringBytes longest accepted string boolean rejectScalarCoercion, int maxDepth, int maxArrayElements, int maxStringBytes) { public static WebJsonProfile strict() { return new WebJsonProfile(true, true, true, true, true, 64, 100_000, 1_048_576); } maxArrayElements() 를 부르는 자리 : (0) # 같은 이름의 필드가 예산 타입에도 있다 22: * @param maxArrayElements most elements accepted in one JSON array 33: int maxArrayElements, 51: private static final int ABSOLUTE_ARRAY_ELEMENTS_MAX = 100_000; 59: requirePositive(maxArrayElements, "maxArrayElements"); 85: requireAtMost(maxArrayElements, ABSOLUTE_ARRAY_ELEMENTS_MAX, "maxArrayElements"); 110: ABSOLUTE_ARRAY_ELEMENTS_MAX, 123: && maxArrayElements <= other.maxArrayElements 프로덕션이 등록하는 값과 그 필드 순서 : * @param maxExecutionTime longest this operation may run before its deadline expires * @param maxResponseBytes largest response this operation may produce */ public record WebRequestBudget( int maxUriBytes, int maxHeaderBytes, int maxQueryParameters, long maxBodyBytes, int maxJsonDepth, int maxArrayElements, int maxMultipartParts, public static WebRequestBudget standard() { return new WebRequestBudget( 2048, 8192, 64, 256L * 1024, 32, 1_000, 16, Duration.ofSeconds(10), 4L * 1024 * 1024); } 절대 상한을 쓰는 술어를 프로덕션에서 부르는 자리 : test · WebRequestBudgetTest.java:43 assertThat(WebRequestBudget.standard().withinPlatformMaximum()).isTrue(); test · WebRequestBudgetTest.java:58 () -> catalog.registerOverride(new WebBudgetProfileName("orders.bulk"), base, tighter)) test · WebRequestBudgetTest.java:66 catalog.registerOverride( 그 예산 목록은 프로덕션 자동설정이 만들고, 등록하는 예산은 하나다 : WebMvcPlatformAutoConfiguration.java:67 WebBudgetCatalog catalog = new WebBudgetCatalog(); WebMvcPlatformAutoConfiguration.java:68 catalog.register(WebBudgetProfileName.standard(), WebRequestBudget.standard()); WebFluxPlatformAutoConfiguration.java:85 WebBudgetCatalog catalog = new WebBudgetCatalog(); WebFluxPlatformAutoConfiguration.java:86 catalog.register(WebBudgetProfileName.standard(), WebRequestBudget.standard()); WebRequestBudget 의 공개 팩토리 : 1 # 그 예산을 강제하는 필터가 실제로 읽는 필드 budget.maxBodyBytes() budget.maxHeaderBytes() budget.maxQueryParameters() budget.maxResponseBytes() budget.maxUriBytes() 반응형 필터가 자기 파일에서 읽는 필드 : budget.maxBodyBytes() budget.maxHeaderBytes() budget.maxQueryParameters() budget.maxUriBytes() 나머지 둘은 이 감싼 교환에 넘겨 잰다 : 64: .filter(new BoundedServerWebExchange(exchange, budget)) budget.maxBodyBytes() budget.maxResponseBytes() 두 필터를 등록하는 자리 : webfluxContractTest · ReactiveBudgetFixtureApplication.java testkit · BudgetFixtureApplication.java # 유계 팩토리가 파서에 거는 것과 그 이유 /** * Builds the reader whose limits are enforced before a document is materialised. * *
The constraints go on the {@code JsonFactory} rather than being checked after parsing, and
* that placement is the whole point. A depth limit applied to a parsed tree has already paid for
* the tree; a nesting bomb is cheap to send and expensive to hold, so the only limit that helps is
* one the streaming parser refuses to exceed.
JsonFactoryBuilder builder =
JsonFactory.builder()
.streamReadConstraints(
StreamReadConstraints.builder()
.maxNestingDepth(profile.maxDepth())
.maxStringLength(profile.maxStringBytes())
.build());
if (profile.rejectDuplicateKeys()) {
builder.enable(StreamReadFeature.STRICT_DUPLICATE_DETECTION);
}
return builder.build();
# 파서가 실제로 제공하는 상한 전부
jackson-core-3.1.5.jar
maxNestingDepth(int)
maxDocumentLength(long)
maxTokenCount(long)
maxNumberLength(int)
maxStringLength(int)
maxNameLength(int)
유계 팩토리를 부르는 자리와 그것을 부르는 자동설정 :
WebMvcPlatformAutoConfiguration.java:135 return WebObjectMapperFactory.jsonMapper(
WebFluxPlatformAutoConfiguration.java:129 return WebObjectMapperFactory.jsonMapper(WebJsonProfile.strict());
WebObjectMapperFactory.java:59 JsonMapper.builder(BoundedJsonFactory.create(profile))
그중 이 저장소가 이미 쓰는 것 :
JacksonMessageCodec.java:213 .maxDocumentLength(maxBytes)
StrictWebSocketJsonCodec.java:64 .maxDocumentLength(budget.maxMessageBytes())
WebSocketCborCodec.java:76 .maxDocumentLength(binary.maxMessageBytes())
WebCborMapperFactory.java:55 .maxDocumentLength(budget.maxBodyBytes())
WebXmlMapperFactory.java:74 .maxDocumentLength(budget.maxBodyBytes())
LocalJsonSchemaRegistry.java:623 .maxDocumentLength(limits.maximumEnvelopeBytes())
같은 어댑터의 두 자리가 받는 예산 타입과 그 출하값 :
WebCborMapperFactory.java:41 public static ObjectMapper create(CodecBudget budget) {
WebXmlMapperFactory.java:39 public static ObjectMapper create(CodecBudget budget) {
WebXmlMapperFactory.java:56 public static ObjectMapper create(CodecBudget budget, XMLInputFactory input) {
21: int maxBodyBytes,
43: public static CodecBudget conventional(WebRepresentation representation) {
여섯 자리를 실제로 만드는 곳 :
main · JacksonMessageCodec.java:66 public static JacksonMessageCodec of(Map