about 5 years ago
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