對 spring中的 @RequestBody json 請求資料做 XSS過濾
阿新 • • 發佈:2018-12-09
關於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
該方案無法對單個欄位做特殊處理,全部會被轉義。