OWASP Java 2017-02-19 Release 一版小更新 就順便把它加進來 SpringBoot 用來過濾 Json 中的非法字元。
非 Json 的自己每一個變數都要自己加
先加入依賴
<dependency> <groupId>org.owasp.encoder</groupId> <artifactId>encoder</artifactId> <version>1.2.1</version> </dependency>
訂製所有 Stirng 型態的反序列功能
import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.deser.ContextualDeserializer; import org.owasp.encoder.Encode; import java.io.IOException; import java.util.ArrayList; import java.util.List; public class StringDeserializerEscapeXSSCharacter extends JsonDeserializer<String> implements ContextualDeserializer { private List<String> noEscapeList = new ArrayList<>(); @Override public String deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException { String data = null; if (null != jsonParser.getText()) { if (noEscapeList.contains(jsonParser.getCurrentValue().getClass().getName() + "." + jsonParser.getCurrentName())) { data = jsonParser.getText(); } else { data = Encode.forHtml(jsonParser.getText()); } } return data; } @Override public JsonDeserializer<?> createContextual(DeserializationContext deserializationContext, BeanProperty beanProperty) throws JsonMappingException { System.out.println("BeanProperty1 " + beanProperty.getMetadata()); // com.fasterxml.jackson.databind.PropertyMetadata@6314f57f System.out.println("BeanProperty2 " + beanProperty.getFullName()); // username System.out.println("BeanProperty3 " + beanProperty.getType()); // [simple type, class java.lang.String] System.out.println("BeanProperty4 " + beanProperty.getName()); // username System.out.println("BeanProperty5 " + beanProperty.getMember()); // [method com.pousheng.marketingactivity.admin.TestDto#setUsername(1 params)] System.out.println("BeanProperty5.1 " + beanProperty.getMember().getDeclaringClass()); // class com.pousheng.marketingactivity.admin.TestDto System.out.println("BeanProperty5.2 " + beanProperty.getMember().getDeclaringClass().getName()); // com.pousheng.marketingactivity.admin.TestDto System.out.println("BeanProperty5.3 " + beanProperty.getMember().getName()); // setUsername System.out.println("BeanProperty5.4 " + beanProperty.getMember().getAnnotated()); // public void com.pousheng.marketingactivity.admin.TestDto.setUsername(java.lang.String) System.out.println("BeanProperty5.5 " + beanProperty.getMember().getTypeContext()); // [AnnotedClass com.pousheng.marketingactivity.admin.TestDto] System.out.println("BeanProperty6 " + beanProperty.getWrapperName()); // null if (null != beanProperty) { NoEscapeXSSCharacter xssAnnotation = beanProperty.getAnnotation(NoEscapeXSSCharacter.class); if (null != xssAnnotation) { noEscapeList.add(beanProperty.getMember().getDeclaringClass().getName() + "." + beanProperty.getName()); } } return this; } }
然後既然要 Encode 非法,自然有需求某些不要 Encode 掉,比如說網頁編輯器的東西
import com.fasterxml.jackson.annotation.JacksonAnnotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target({ElementType.FIELD, ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @JacksonAnnotation // important so that it will get included! public @interface NoEscapeXSSCharacter { }
配置
@Slf4j @Configuration public class ActivityConfig { @Autowired private Environment environment; @Autowired private MarketingActivityAdminProperties marketingActivityAdminProperties; @Autowired public void configeJackson(ObjectMapper objectMapper) { SimpleModule module = new SimpleModule(); module.addDeserializer(String.class, new StringDeserializerXSSCharacterEscape()); objectMapper.registerModule(module); } }
範例Dto
@Data public class TestDto { private Long id; @NoEscapeXSSCharacter private String username; private String name; }
測試一下
@Autowired private ObjectMapper mapper; TestDto testDto = mapper.readValue("{/"id/":/"5/",/"username/":/"<script>alert('好的');</script>/",/"name/":/"<script>alert('好的');</script>/"}", TestDto.class); System.out.println(testDto);
結果
TestDto(id=5, username=<script>alert('好的');</script>, name=<script>alert('好的');</script>)
參考資料
http://owasp.github.io/owasp-java-encoder/
https://github.com/OWASP/owasp-java-encoder← Springboot multipart max-file-size Exception