1. 程式人生 > >對 spring中的 @RequestBody json 請求資料做 XSS過濾

對 spring中的 @RequestBody json 請求資料做 XSS過濾

關於xss過濾,網上大都是是對 param的,這個很多文章了 定義過濾器。XSSFilter 不說了,

還有就是對所有@ResponseBody 返回內容做XSS過濾的方案:

MappingJackson2HttpMessageConverter 的objectMapper 做設定

參考 百度

那麼對 @RequestBody  的 json 資料怎麼過濾呢:

spring處理json是通過MappingJackson2HttpMessageConverter實現的。

自定義XSSMappingJackson2HttpMessageConverter 替換掉spring自帶的,重寫 read方法:

public class XSSMappingJackson2HttpMessageConverter extends
        MappingJackson2HttpMessageConverter {

    private ObjectMapper mapper = new ObjectMapper();

    public XSSMappingJackson2HttpMessageConverter() {
        super();
        mapper.getFactory().setCharacterEscapes(new HTMLCharacterEscapes());
    }

    @Override
    public Object read(Type type, Class<?> contextClass,
                       HttpInputMessage inputMessage) throws IOException,
            HttpMessageNotReadableException {
        JavaType javaType = getJavaType(type, contextClass);

        // 下面的程式碼 將 @RequestBody 中的資料 做 XSS過濾
        try {
            // json字串轉為物件
            Object object = mapper.readValue(inputMessage.getBody(), javaType);

            // 物件轉字串
            String jsonString = mapper.writeValueAsString(object);

            // json字串轉物件
            object = mapper.readValue(jsonString, javaType);
            return object;
        } catch (IOException ex) {
            throw new HttpMessageNotReadableException("Could not read JSON: "
                    + ex.getMessage(), ex);
        }

    }

}

其中用到的 HTMLCharacterEscapes類:

import com.fasterxml.jackson.core.SerializableString;
import com.fasterxml.jackson.core.io.CharacterEscapes;
import com.fasterxml.jackson.core.io.SerializedString;
import org.apache.commons.lang3.StringEscapeUtils;

public class HTMLCharacterEscapes extends CharacterEscapes {

    private final int[] asciiEscapes;

    public HTMLCharacterEscapes() {
        // start with set of characters known to require escaping (double-quote, backslash etc)
        asciiEscapes = CharacterEscapes.standardAsciiEscapesForJSON();
        // and force escaping of a few others:
        asciiEscapes['<'] = CharacterEscapes.ESCAPE_CUSTOM;
        asciiEscapes['>'] = CharacterEscapes.ESCAPE_CUSTOM;
        asciiEscapes['&'] = CharacterEscapes.ESCAPE_CUSTOM;
        asciiEscapes['"'] = CharacterEscapes.ESCAPE_CUSTOM;
        asciiEscapes['\''] = CharacterEscapes.ESCAPE_CUSTOM;
    }

    @Override
    public int[] getEscapeCodesForAscii() {
        return asciiEscapes;
    }

    // and this for others; we don't need anything special here
    @Override
    public SerializableString getEscapeSequence(int ch) {
        return new SerializedString(StringEscapeUtils.escapeHtml4(Character.toString((char) ch)));
    }
}

XSSMappingJackson2HttpMessageConverter 之所以沒有用父類的 objectMapper,是為了互不影響。

至於XSSMappingJackson2HttpMessageConverter 怎麼替換掉spring自帶的:

spring 的專案改<bean> 配置

springboot專案可以直接定一個 bean

@Bean
    public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() {
        MappingJackson2HttpMessageConverter htmlEscapingConverter = new XSSMappingJackson2HttpMessageConverter();
        return htmlEscapingConverter;
    }

Done

該方案無法對單個欄位做特殊處理,全部會被轉義。