很久沒有寫博客了,這兩天遇到一個關於url編碼的問題,作一個記錄 java
需求是這樣的;spring
系統遭受不法人員攻擊,老大系統系統寫一個過濾器,當有安全攻擊的時候,直接經過配置的方式禁止該接口的使用瀏覽器
原本覺得很簡單 ,直接寫了一個定時加載的功能,讀取配置,而後與請求過來的url進行對比便可,用瀏覽器測試都沒有問題,可是通過安全的時候,問題來了,在瀏覽器中會url自動的解析,可是在當在抓起工具中輸入如下地址,仍然能請求道相應的請求,安全
/product/./queryChannelProductInfo
/product/123/../queryChannelProductInfo
/product%2fqueryChannelProductInfo服務器
從表面現象能夠看出,服務器底層還有一個層與瀏覽器作了一樣的規則處理 mvc
一開始處理的方式 , 獲取器Dispatcher,經過反射而後獲取器url,而後在進行比較 app
RequestDispatcher dispatcher = arg0.getRequestDispatcher(reqUrl); @SuppressWarnings("deprecation") Field path = arg0.getRequestDispatcher(URLDecoder.decode(reqUrl)).getClass().getDeclaredFields()[16]; path.setAccessible(true); path.get(dispatcher); String dispatcherUrl =(String) path.get(dispatcher); if (new AntPathMatcher().match(strUrl,dispatcherUrl)) { logger.warn(reqUrl + "have no authority for rquest"); return; }
這種方法解決了./ ../這種方式,可是url編碼的格式仍然能夠繞過 框架
一時分析,框架用的是springmvc 應該是在內容的處理致使的 ,因而開始分析spring mvc 的源碼 async
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { HttpServletRequest processedRequest = request; HandlerExecutionChain mappedHandler = null; boolean multipartRequestParsed = false; WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request); try { try { ModelAndView mv = null; Exception dispatchException = null; try { processedRequest = this.checkMultipart(request); multipartRequestParsed = processedRequest != request; mappedHandler = this.getHandler(processedRequest, false); if (mappedHandler == null || mappedHandler.getHandler() == null) { this.noHandlerFound(processedRequest, response); return; } ...... }
@Deprecated protected HandlerExecutionChain getHandler(HttpServletRequest request, boolean cache) throws Exception { return this.getHandler(request); } protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { Iterator i$ = this.handlerMappings.iterator(); HandlerExecutionChain handler; do { if (!i$.hasNext()) { return null; } HandlerMapping hm = (HandlerMapping)i$.next(); if (this.logger.isTraceEnabled()) { this.logger.trace("Testing handler map [" + hm + "] in DispatcherServlet with name '" + this.getServletName() + "'"); } handler = hm.getHandler(request); } while(handler == null); return handler; }
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { Object handler = getHandlerInternal(request); if (handler == null) { handler = getDefaultHandler(); } if (handler == null) { return null; } if (handler instanceof String) { String handlerName = (String) handler; handler = getApplicationContext().getBean(handlerName); } return getHandlerExecutionChain(handler, request); }
protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) { HandlerExecutionChain chain = new HandlerExecutionChain(handler); chain.addInterceptors(getAdaptedInterceptors()); String lookupPath = this.urlPathHelper.getLookupPathForRequest(request); for (MappedInterceptor mappedInterceptor : this.mappedInterceptors) { if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) { chain.addInterceptor(mappedInterceptor.getInterceptor()); } } return chain; }