5 months 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 型態的反序列功能

StringDeserializerXSSCharacterEscape.java
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 掉,比如說網頁編輯器的東西

NoEscapeXSSCharacter.java
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 {
}

配置

ActivityConfig.java
@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

TestDto.java
@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=&lt;script&gt;alert(&#39;好的&#39;);&lt;/script&gt;)

參考資料
http://owasp.github.io/owasp-java-encoder/
https://github.com/OWASP/owasp-java-encoder

← Springboot multipart max-file-size Exception Configuring Visual Studio Code Run SpringBoot →
 
comments powered by Disqus