/* org.springframework.web.servlet.handler.AbstractHandlerMapping 類 */ public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport implements HandlerMapping, Ordered { private int order = Integer.MAX_VALUE; // default: same as non-Ordered private Object defaultHandler; private UrlPathHelper urlPathHelper = new UrlPathHelper(); private PathMatcher pathMatcher = new AntPathMatcher(); /* 省略代碼... */ 其中UrlPathHelper 類中包含decodePathVariables和decodeMatrixVariables兩個方法即為抽取path參數,所以自訂一個UrlPathHelper來完成參數過濾功能。然後所有AbstractHandlerMapping均使用自訂UrlPathHelper即可。但是需要注意的是SpringMVC預設產生了兩個HandlerMapping->RequestMappingHandlerMapping和BeanNameUrlHandlerMapping,其是在WebMvcConfigurationSupport這個類中產生的,所有必須設定這兩個HandlerMapping的urlPathHelper,沒有直接的調用介面,那麼監聽Spring的bean執行個體化即可,建立類如下: /* 解決@PathVariable註解造成的xss攻擊問題,注意:此類必需由WebApplicationContext初始化 */ public class XssHandlerMappingPostProcessor implements BeanPostProcessor{ @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException{ return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException{ if(bean instanceof AbstractHandlerMapping){ AbstractHandlerMapping ahm = (AbstractHandlerMapping) bean; ahm.setUrlPathHelper(new XssUrlPathHelper()); } return bean; } static class XssUrlPathHelper extends UrlPathHelper{ @Override public Map<String, String> decodePathVariables(HttpServletRequest request, Map<String, String> vars){ Map<String, String> result = super.decodePathVariables(request, vars); if(!CollectionUtils.isEmpty(result)){ for(String key : result.keySet()){ result.put(key, cleanXSS(result.get(key))); } } return result; } @Override public MultiValueMap<String, String> decodeMatrixVariables(HttpServletRequest request, MultiValueMap<String, String> vars){ MultiValueMap<String, String> mvm = super.decodeMatrixVariables(request, vars); if(!CollectionUtils.isEmpty(mvm)){ for(String key : mvm.keySet()){ List<String> value = mvm.get(key); for(int i = 0; i < value.size(); i++){ value.set(i, cleanXSS(value.get(i))); } } } return mvm; } private String cleanXSS(String value){ return HtmlUtils.htmlEscape(value); } } } |