From ba314a79bd7a0b73d5dad794fb5e718dc00042b2 Mon Sep 17 00:00:00 2001 From: wenshao Date: Tue, 14 Aug 2012 14:33:26 +0800 Subject: [PATCH] web stat support error 404 --- .../druid/support/http/WebStatFilter.java | 92 ++++++++++++++++--- .../druid/support/http/stat/WebAppStat.java | 26 ++++-- .../druid/support/http/stat/WebURIStat.java | 6 +- .../druid/bvt/filter/wall/OracleWallTest.java | 1 + 4 files changed, 99 insertions(+), 26 deletions(-) diff --git a/src/main/java/com/alibaba/druid/support/http/WebStatFilter.java b/src/main/java/com/alibaba/druid/support/http/WebStatFilter.java index d0e04f2aaf..82aeccaeff 100644 --- a/src/main/java/com/alibaba/druid/support/http/WebStatFilter.java +++ b/src/main/java/com/alibaba/druid/support/http/WebStatFilter.java @@ -1,6 +1,7 @@ package com.alibaba.druid.support.http; import java.io.IOException; +import java.io.PrintWriter; import java.util.Arrays; import java.util.HashSet; import java.util.Set; @@ -13,6 +14,8 @@ import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpServletResponseWrapper; import javax.servlet.http.HttpSession; import com.alibaba.druid.filter.stat.StatFilterContext; @@ -21,6 +24,7 @@ import com.alibaba.druid.support.http.stat.WebAppStat; import com.alibaba.druid.support.http.stat.WebAppStatManager; import com.alibaba.druid.support.http.stat.WebRequestStat; import com.alibaba.druid.support.http.stat.WebSessionStat; +import com.alibaba.druid.support.http.stat.WebURIStat; import com.alibaba.druid.support.logging.Log; import com.alibaba.druid.support.logging.LogFactory; import com.alibaba.druid.support.spring.stat.SpringMethodStat; @@ -30,6 +34,8 @@ import com.alibaba.druid.util.ServletPathMatcher; public class WebStatFilter implements Filter { + public final static int STATUS_NOT_FOUND = 404; + public final static String PARAM_NAME_SESSION_STAT_ENABLE = "sessionStatEnable"; public final static String PARAM_NAME_SESSION_STAT_MAX_COUNT = "sessionStatMaxCount"; public static final String PARAM_NAME_EXCLUSIONS = "exclusions"; @@ -62,6 +68,8 @@ public class WebStatFilter implements Filter { public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest httpRequest = (HttpServletRequest) request; + HttpServletResponse httpResponse = (HttpServletResponse) response; + StatHttpServletResponseWrapper responseWrapper = new StatHttpServletResponseWrapper(httpResponse); final String requestURI = getRequestURI(httpRequest); @@ -76,7 +84,14 @@ public class WebStatFilter implements Filter { WebRequestStat requestStat = new WebRequestStat(startNano); WebRequestStat.set(requestStat); WebSessionStat sessionStat = getSessionStat(httpRequest); - webAppStat.beforeInvoke(requestURI); + webAppStat.beforeInvoke(); + + WebURIStat uriStat = webAppStat.getURIStat(requestURI, false); + + // 第一次访问时,uriStat这里为null,是为了防止404攻击。 + if (uriStat != null) { + uriStat.beforeInvoke(); + } // 第一次访问时,sessionId为null,如果缺省sessionCreate=false,sessionStat就为null。 if (sessionStat != null) { @@ -86,7 +101,7 @@ public class WebStatFilter implements Filter { Throwable error = null; try { - chain.doFilter(request, response); + chain.doFilter(request, responseWrapper); } catch (IOException e) { error = e; throw e; @@ -103,23 +118,37 @@ public class WebStatFilter implements Filter { long endNano = System.nanoTime(); requestStat.setEndNano(endNano); - long nanoSpan = endNano - startNano; - webAppStat.afterInvoke(error, nanoSpan); + long nanos = endNano - startNano; + webAppStat.afterInvoke(error, nanos); - if (sessionStat != null) { - sessionStat.afterInvoke(error, nanoSpan); - sessionStat.setPrincipal(getPrincipal(httpRequest)); - } else { + if (sessionStat == null) { sessionStat = getSessionStat(httpRequest); if (sessionStat != null) { - sessionStat.setLastAccessTimeMillis(startMillis); - sessionStat.reacord(nanoSpan); - sessionStat.incrementRequestCount(); - - sessionStat.setPrincipal(getPrincipal(httpRequest)); + sessionStat.beforeInvoke(); // 补偿 } } + if (sessionStat != null) { + sessionStat.afterInvoke(error, nanos); + sessionStat.setPrincipal(getPrincipal(httpRequest)); + } + + if (uriStat == null) { + if (responseWrapper.getStatus() == STATUS_NOT_FOUND) { + uriStat = webAppStat.getURIStat("error_404", true); + } else { + uriStat = webAppStat.getURIStat(requestURI, true); + } + + if (uriStat != null) { + uriStat.beforeInvoke(); // 补偿调用 + } + } + + if (uriStat != null) { + uriStat.afterInvoke(error, nanos); + } + WebRequestStat.set(null); } } @@ -406,4 +435,41 @@ public class WebStatFilter implements Filter { } } } + + public final static class StatHttpServletResponseWrapper extends HttpServletResponseWrapper implements HttpServletResponse { + + private int status; + + public StatHttpServletResponseWrapper(HttpServletResponse response){ + super(response); + } + + public void setStatus(int statusCode) { + super.setStatus(statusCode); + this.status = statusCode; + } + + public void setStatus(int statusCode, String statusMessage) { + super.setStatus(statusCode, statusMessage); + this.status = statusCode; + } + + public void sendError(int statusCode, String statusMessage) throws IOException { + super.sendError(statusCode, statusMessage); + this.status = statusCode; + } + + public void sendError(int statusCode) throws IOException { + super.sendError(statusCode); + this.status = statusCode; + } + + public int getStatus() { + return status; + } + + public PrintWriter getWriter() throws IOException { + return super.getWriter(); + } + } } diff --git a/src/main/java/com/alibaba/druid/support/http/stat/WebAppStat.java b/src/main/java/com/alibaba/druid/support/http/stat/WebAppStat.java index c93fee3d76..fe48c6bc51 100644 --- a/src/main/java/com/alibaba/druid/support/http/stat/WebAppStat.java +++ b/src/main/java/com/alibaba/druid/support/http/stat/WebAppStat.java @@ -88,7 +88,7 @@ public class WebAppStat { return contextPath; } - public void beforeInvoke(String uri) { + public void beforeInvoke() { currentLocal.set(this); int running = runningCount.incrementAndGet(); @@ -107,15 +107,23 @@ public class WebAppStat { } requestCount.incrementAndGet(); - - WebURIStat uriStat = getURIStat(uri); - - if (uriStat != null) { - uriStat.beforeInvoke(uri); - } + } + + public WebURIStat getURIStat(String uri) { + return getURIStat(uri, false); } - public WebURIStat getURIStat(String uri) { + public WebURIStat getURIStat(String uri, boolean create) { + WebURIStat uriStat = uriStatMap.get(uri); + + if (uriStat != null) { + return uriStat; + } + + if (!create) { + return null; + } + if (uriStatMap.size() >= this.getMaxStatUriCount()) { long fullCount = uriStatMapFullCount.getAndIncrement(); @@ -126,8 +134,6 @@ public class WebAppStat { return null; } - WebURIStat uriStat = uriStatMap.get(uri); - if (uriStat == null) { uriStatMap.putIfAbsent(uri, new WebURIStat(uri)); uriStat = uriStatMap.get(uri); diff --git a/src/main/java/com/alibaba/druid/support/http/stat/WebURIStat.java b/src/main/java/com/alibaba/druid/support/http/stat/WebURIStat.java index de5c165322..f28fc811f1 100644 --- a/src/main/java/com/alibaba/druid/support/http/stat/WebURIStat.java +++ b/src/main/java/com/alibaba/druid/support/http/stat/WebURIStat.java @@ -42,7 +42,7 @@ public class WebURIStat { return uri; } - public void beforeInvoke(String uri) { + public void beforeInvoke() { currentLocal.set(this); int running = runningCount.incrementAndGet(); @@ -63,9 +63,9 @@ public class WebURIStat { requestCount.incrementAndGet(); } - public void afterInvoke(Throwable error, long nanoSpan) { + public void afterInvoke(Throwable error, long nanos) { runningCount.decrementAndGet(); - requestTimeNano.addAndGet(nanoSpan); + requestTimeNano.addAndGet(nanos); { WebRequestStat localStat = WebRequestStat.current(); diff --git a/src/test/java/com/alibaba/druid/bvt/filter/wall/OracleWallTest.java b/src/test/java/com/alibaba/druid/bvt/filter/wall/OracleWallTest.java index 55b154305a..f742681ab9 100644 --- a/src/test/java/com/alibaba/druid/bvt/filter/wall/OracleWallTest.java +++ b/src/test/java/com/alibaba/druid/bvt/filter/wall/OracleWallTest.java @@ -12,5 +12,6 @@ public class OracleWallTest extends TestCase { Assert.assertFalse(WallUtils.isValidateOracle("select f1, f2 from t union select 1, 2")); Assert.assertFalse(WallUtils.isValidateOracle("select * from TAB")); + Assert.assertFalse(WallUtils.isValidateOracle("select * from ALL_TABLES where (1=1 or (1+1)=2) and (4=8 or 1=1)")); } }