在工做中,須要對xss攻擊腳本過濾,在此記錄下處理過程。java
因爲只須要對content-type=application/json;charset=UTF-8的json請求進行處理,因此須要重寫MappingJacksonHttpMessageConverter部分方法。spring
注意:若是使用的是MappingJackson2HttpMessageConverter,須要重寫MappingJackson2HttpMessageConverter部分方法 json
定義接口MessageConverterHandlermvc
咱們定義一個接口來定義咱們須要實現的方法
app
public interface MessageConverterHandler<T, K> { /** * 用於在httpMessageConverter read(..)方法完成以後調用 * <p> * 1.能夠對converter映射出的Object進行處理 * </p> */ public Object readAfter( T obj, K type ); }
2.自定義註解NeedXssxss
該註解用於須要xss過濾的字段ide
@Target( ElementType.FIELD ) @Retention( RetentionPolicy.RUNTIME ) @Documented public @interface NeedXss { }
3.實現類XssMappingJacksonHttpMessageConverter,該類須要實現MessageConverterHandler,繼承MappingJacksonHttpMessageConverterthis
代碼以下:
編碼
//默認會過濾全部請求路徑,只會過濾String類型的字段,須要其餘類型過濾的請自行完善 public class XssMappingJacksonHttpMessageConverter extends MappingJacksonHttpMessageConverter implements MessageConverterHandler<Object, Type> { /** * 不須要xss過濾的路徑 */ protected static List<String> urls; static { urls = new ArrayList<String>(); // for example urls.add("/xxx/xxxxx"); } //重寫該方法,咱們只須要加上Object tempObj = this.process( obj, type, inputMessage ); //並返回tempObj,process方法裏面咱們過濾白名單和進行xss處理 @Override public Object read( Type type, Class<?> contextClass, HttpInputMessage inputMessage ) throws IOException, HttpMessageNotReadableException { JavaType javaType = getJavaType( type, contextClass ); Object obj = readJavaType( javaType, inputMessage ); Object tempObj = this.process( obj, type, inputMessage ); return tempObj; } //這個就是父類的readJavaType方法,因爲父類該方法是private的,因此咱們copy一個用 private Object readJavaType( JavaType javaType, HttpInputMessage inputMessage ) { try { return super.getObjectMapper().readValue( inputMessage.getBody(), javaType ); } catch ( IOException ex ) { throw new HttpMessageNotReadableException( "Could not read JSON: " + ex.getMessage(), ex ); } } protected Object process( Object obj, Type type, HttpInputMessage inputMessage ) { if ( this.isNeedProcess( inputMessage ) ) { return this.readAfter( obj, type ); } else { return obj; } } //根據白名單,判斷當前請求路徑是否須要xss過濾 protected boolean isNeedProcess( HttpInputMessage inputMessage ) { String url = ""; try { //通過debug發現inputMessage類型爲ServletServerHttpRequest,因此進行下類型轉換 ServletServerHttpRequest request = ( ServletServerHttpRequest ) inputMessage; url = request.getURI().getPath(); //根據白名單作下匹配,固然也能夠實現正則什麼的,代碼就不貼了 } catch ( Exception e ) { logger.error( "BACK_ERROR," + this.getClass().getCanonicalName() + ",XSS處理-url處理失敗,url=" + url + ",ERROR=", e ); return true; } return true; } //最重要的一步,進行xss過濾 @Override public Object readAfter( Object obj, Type type ) { try { //type實際上就是咱們須要convert的model,咱們經過反射來完成根據NeedXss註解對String //的字段進行xss過濾 Class clazz = Class.forName( JSON.toJSONString( type ).replace( "\"", "" ) ); if ( clazz == null ) { return obj; } Field[] fields = clazz.getDeclaredFields(); if ( fields != null && fields.length > 0 ) { // string類型字段名稱列表 List<String> strList = new ArrayList<String>( fields.length ); // 1. 將須要xss處理的string類型的字段放入strlist for ( int i = 0; i < fields.length; i++ ) { // 1.1該屬性是否有NeedXss.class註解 NeedXss needXss = fields[ i ].getAnnotation( NeedXss.class ); // 1.2若是該沒有NeedXss.class註解,則不處理該屬性 if ( needXss == null || !( needXss instanceof NeedXss ) ) { continue; } String mod = Modifier.toString( fields[ i ].getModifiers() ); if ( mod.indexOf( "static" ) != -1 ) continue; // 獲得屬性的類名 String className = fields[ i ].getType().getSimpleName(); // 獲得屬性字段名 if ( className.equalsIgnoreCase( "String" ) ) { strList.add( fields[ i ].getName() ); } } // 2.將strlist中的字段進行xss處理 if ( strList.size() > 0 ) { Object temp = JSON.toJavaObject( ( JSON ) JSON.toJSON( obj ), clazz ); for ( int i = 0; i < strList.size(); i++ ) { Method set = clazz.getMethod( "set" + strList.get( i ).substring( 0, 1 ).toUpperCase() + strList.get( i ).substring( 1 ), String.class ); Method get = clazz.getMethod( "get" + strList.get( i ).substring( 0, 1 ).toUpperCase() + strList.get( i ).substring( 1 ) ); Object tempObj = get.invoke( temp ); if ( tempObj == null ) { break; } String content = tempObj.toString(); set.invoke( temp, StringUtils.cleanXss( content ) ); } return temp; } } } catch ( Exception e ) { logger.error( "BACK_ERROR," + this.getClass().getCanonicalName() + ",XSS處理失敗,obj=" + JSON.toJSONString( obj ) + ",javaType=" + JSON.toJSONString( type ) + ",ERROR=", e ); return obj; } return obj; } }
4.配置使用自定義的XssMappingJacksonHttpMessageConverterurl
在SpringMVC的配置文件裏面加上下面的配置
<mvc:annotation-driven > <mvc:message-converters register-defaults="true"> <!-- 將StringHttpMessageConverter的默認編碼設爲UTF-8. --> <bean class="org.springframework.http.converter.StringHttpMessageConverter"> <constructor-arg value="UTF-8" /> </bean> <bean class="com.zhubajie.seller.common.converter.XssMappingJacksonHttpMessageConverter"> <property name="prettyPrint" value="false" /> </bean> </mvc:message-converters> </mvc:annotation-driven>
最後,不出意外應該就是能夠啦