From be307700c22439f2f59de257bf7a5d0e07907a51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=AB=98=E9=93=81?= Date: Tue, 16 Feb 2021 22:42:56 +0800 Subject: [PATCH] improved druid monitor, add StatViewFilter --- .../support/http/AbstractWebStatImpl.java | 20 + .../druid/support/http/ResourceServlet.java | 382 ++++++++++-------- .../druid/support/http/StatViewFilter.java | 112 ++++- .../druid/support/http/StatViewServlet.java | 32 ++ 4 files changed, 365 insertions(+), 181 deletions(-) diff --git a/src/main/java/com/alibaba/druid/support/http/AbstractWebStatImpl.java b/src/main/java/com/alibaba/druid/support/http/AbstractWebStatImpl.java index 88fb3039bc..adccaf2d36 100644 --- a/src/main/java/com/alibaba/druid/support/http/AbstractWebStatImpl.java +++ b/src/main/java/com/alibaba/druid/support/http/AbstractWebStatImpl.java @@ -90,6 +90,7 @@ public class AbstractWebStatImpl { WebSessionStat sessionStat = null; String sessionId = getSessionId(request); + if (sessionId != null) { sessionStat = webAppStat.getSessionStat(sessionId, true); } @@ -139,6 +140,25 @@ public class AbstractWebStatImpl { HttpSession session = httpRequest.getSession(createSession); if (session != null) { sessionId = session.getId(); + } else { + Cookie[] cookies = httpRequest.getCookies(); + if (cookies != null) { + for (Cookie cookie : cookies) { + if (cookie.getName().equals("JSESSIONID")) { + sessionId = cookie.getValue(); + break; + } + } + + if (sessionId == null) { + for (Cookie cookie : cookies) { + if (cookie.getName().equals("JWT-SESSION")) { + sessionId = cookie.getValue(); + break; + } + } + } + } } return sessionId; diff --git a/src/main/java/com/alibaba/druid/support/http/ResourceServlet.java b/src/main/java/com/alibaba/druid/support/http/ResourceServlet.java index f3959b5a23..46526037e3 100644 --- a/src/main/java/com/alibaba/druid/support/http/ResourceServlet.java +++ b/src/main/java/com/alibaba/druid/support/http/ResourceServlet.java @@ -44,18 +44,10 @@ public abstract class ResourceServlet extends HttpServlet { public static final String PARAM_NAME_DENY = "deny"; public static final String PARAM_REMOTE_ADDR = "remoteAddress"; - protected String username = null; - protected String password = null; - - protected List allowList = new ArrayList(); - protected List denyList = new ArrayList(); - - protected final String resourcePath; - - protected String remoteAddressHeader = null; + protected final ResourceHandler handler; public ResourceServlet(String resourcePath){ - this.resourcePath = resourcePath; + handler = new ResourceHandler(resourcePath); } public void init() throws ServletException { @@ -65,17 +57,17 @@ public abstract class ResourceServlet extends HttpServlet { private void initAuthEnv() { String paramUserName = getInitParameter(PARAM_NAME_USERNAME); if (!StringUtils.isEmpty(paramUserName)) { - this.username = paramUserName; + handler.username = paramUserName; } String paramPassword = getInitParameter(PARAM_NAME_PASSWORD); if (!StringUtils.isEmpty(paramPassword)) { - this.password = paramPassword; + handler.password = paramPassword; } String paramRemoteAddressHeader = getInitParameter(PARAM_REMOTE_ADDR); if (!StringUtils.isEmpty(paramRemoteAddressHeader)) { - this.remoteAddressHeader = paramRemoteAddressHeader; + handler.remoteAddressHeader = paramRemoteAddressHeader; } try { @@ -90,7 +82,7 @@ public abstract class ResourceServlet extends HttpServlet { } IPRange ipRange = new IPRange(item); - allowList.add(ipRange); + handler.allowList.add(ipRange); } } } catch (Exception e) { @@ -110,7 +102,7 @@ public abstract class ResourceServlet extends HttpServlet { } IPRange ipRange = new IPRange(item); - denyList.add(ipRange); + handler.denyList.add(ipRange); } } } catch (Exception e) { @@ -120,183 +112,245 @@ public abstract class ResourceServlet extends HttpServlet { } public boolean isPermittedRequest(String remoteAddress) { - boolean ipV6 = remoteAddress != null && remoteAddress.indexOf(':') != -1; - - if (ipV6) { - return "0:0:0:0:0:0:0:1".equals(remoteAddress) || (denyList.size() == 0 && allowList.size() == 0); - } - - IPAddress ipAddress = new IPAddress(remoteAddress); - - for (IPRange range : denyList) { - if (range.isIPAddressInRange(ipAddress)) { - return false; - } - } - - if (allowList.size() > 0) { - for (IPRange range : allowList) { - if (range.isIPAddressInRange(ipAddress)) { - return true; - } - } - - return false; - } - - return true; + return handler.isPermittedRequest(remoteAddress); } protected String getFilePath(String fileName) { - return resourcePath + fileName; + return handler.resourcePath + fileName; } protected void returnResourceFile(String fileName, String uri, HttpServletResponse response) - throws ServletException, - IOException { - - String filePath = getFilePath(fileName); - - if (filePath.endsWith(".html")) { - response.setContentType("text/html; charset=utf-8"); - } - if (fileName.endsWith(".jpg")) { - byte[] bytes = Utils.readByteArrayFromResource(filePath); - if (bytes != null) { - response.getOutputStream().write(bytes); - } - - return; - } - - String text = Utils.readFromResource(filePath); - if (text == null) { - response.sendRedirect(uri + "/index.html"); - return; - } - if (fileName.endsWith(".css")) { - response.setContentType("text/css;charset=utf-8"); - } else if (fileName.endsWith(".js")) { - response.setContentType("text/javascript;charset=utf-8"); - } - response.getWriter().write(text); + throws ServletException, + IOException { + handler.returnResourceFile(fileName, uri, response); } public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { - String contextPath = request.getContextPath(); String servletPath = request.getServletPath(); - String requestURI = request.getRequestURI(); + handler.service(request, response, servletPath, new ProcessCallback() { - response.setCharacterEncoding("utf-8"); - - if (contextPath == null) { // root context - contextPath = ""; - } - String uri = contextPath + servletPath; - String path = requestURI.substring(contextPath.length() + servletPath.length()); - - if (!isPermittedRequest(request)) { - path = "/nopermit.html"; - returnResourceFile(path, uri, response); - return; - } - - if ("/submitLogin".equals(path)) { - String usernameParam = request.getParameter(PARAM_NAME_USERNAME); - String passwordParam = request.getParameter(PARAM_NAME_PASSWORD); - if (username.equals(usernameParam) && password.equals(passwordParam)) { - request.getSession().setAttribute(SESSION_USER_KEY, username); - response.getWriter().print("success"); - } else { - response.getWriter().print("error"); + @Override + public String process(String url) { + return ResourceServlet.this.process(url); } - return; - } - - if (isRequireAuth() // - && !ContainsUser(request)// - && !checkLoginParam(request)// - && !("/login.html".equals(path) // - || path.startsWith("/css")// - || path.startsWith("/js") // - || path.startsWith("/img"))) { - if (contextPath.equals("") || contextPath.equals("/")) { - response.sendRedirect("/druid/login.html"); - } else { - if ("".equals(path)) { - response.sendRedirect("druid/login.html"); - } else { - response.sendRedirect("login.html"); - } - } - return; - } - - if ("".equals(path)) { - if (contextPath.equals("") || contextPath.equals("/")) { - response.sendRedirect("/druid/index.html"); - } else { - response.sendRedirect("druid/index.html"); - } - return; - } - - if ("/".equals(path)) { - response.sendRedirect("index.html"); - return; - } - - if (path.contains(".json")) { - String fullUrl = path; - if (request.getQueryString() != null && request.getQueryString().length() > 0) { - fullUrl += "?" + request.getQueryString(); - } - response.getWriter().print(process(fullUrl)); - return; - } - - // find file in resources path - returnResourceFile(path, uri, response); + }); } public boolean ContainsUser(HttpServletRequest request) { - HttpSession session = request.getSession(false); - return session != null && session.getAttribute(SESSION_USER_KEY) != null; + return handler.containsUser(request); } public boolean checkLoginParam(HttpServletRequest request) { - String usernameParam = request.getParameter(PARAM_NAME_USERNAME); - String passwordParam = request.getParameter(PARAM_NAME_PASSWORD); - if(null == username || null == password){ - return false; - } else if (username.equals(usernameParam) && password.equals(passwordParam)) { - return true; - } - return false; + return handler.checkLoginParam(request); } public boolean isRequireAuth() { - return this.username != null; + return handler.isRequireAuth(); } public boolean isPermittedRequest(HttpServletRequest request) { - String remoteAddress = getRemoteAddress(request); - return isPermittedRequest(remoteAddress); + return handler.isPermittedRequest(request); } protected String getRemoteAddress(HttpServletRequest request) { - String remoteAddress = null; - - if (remoteAddressHeader != null) { - remoteAddress = request.getHeader(remoteAddressHeader); - } - - if (remoteAddress == null) { - remoteAddress = request.getRemoteAddr(); - } - - return remoteAddress; + return handler.getRemoteAddress(request); } protected abstract String process(String url); + + public static interface ProcessCallback { + String process(String url); + } + + public static class ResourceHandler { + protected String username = null; + protected String password = null; + + protected List allowList = new ArrayList(); + protected List denyList = new ArrayList(); + + protected String resourcePath; + + protected String remoteAddressHeader = null; + + public ResourceHandler(String resourcePath) { + this.resourcePath = resourcePath; + } + + protected void returnResourceFile(String fileName, String uri, HttpServletResponse response) + throws ServletException, + IOException { + + String filePath = getFilePath(fileName); + + if (filePath.endsWith(".html")) { + response.setContentType("text/html; charset=utf-8"); + } + if (fileName.endsWith(".jpg")) { + byte[] bytes = Utils.readByteArrayFromResource(filePath); + if (bytes != null) { + response.getOutputStream().write(bytes); + } + + return; + } + + String text = Utils.readFromResource(filePath); + if (text == null) { + return; + } + + if (fileName.endsWith(".css")) { + response.setContentType("text/css;charset=utf-8"); + } else if (fileName.endsWith(".js")) { + response.setContentType("text/javascript;charset=utf-8"); + } + response.getWriter().write(text); + } + + protected String getFilePath(String fileName) { + return resourcePath + fileName; + } + + public boolean checkLoginParam(HttpServletRequest request) { + String usernameParam = request.getParameter(PARAM_NAME_USERNAME); + String passwordParam = request.getParameter(PARAM_NAME_PASSWORD); + if(null == username || null == password){ + return false; + } else if (username.equals(usernameParam) && password.equals(passwordParam)) { + return true; + } + return false; + } + + protected String getRemoteAddress(HttpServletRequest request) { + String remoteAddress = null; + + if (remoteAddressHeader != null) { + remoteAddress = request.getHeader(remoteAddressHeader); + } + + if (remoteAddress == null) { + remoteAddress = request.getRemoteAddr(); + } + + return remoteAddress; + } + + public boolean containsUser(HttpServletRequest request) { + HttpSession session = request.getSession(false); + return session != null && session.getAttribute(SESSION_USER_KEY) != null; + } + + public boolean isRequireAuth() { + return username != null; + } + + public boolean isPermittedRequest(HttpServletRequest request) { + String remoteAddress = getRemoteAddress(request); + return isPermittedRequest(remoteAddress); + } + + public boolean isPermittedRequest(String remoteAddress) { + boolean ipV6 = remoteAddress != null && remoteAddress.indexOf(':') != -1; + + if (ipV6) { + return "0:0:0:0:0:0:0:1".equals(remoteAddress) || (denyList.size() == 0 && allowList.size() == 0); + } + + IPAddress ipAddress = new IPAddress(remoteAddress); + + for (IPRange range : denyList) { + if (range.isIPAddressInRange(ipAddress)) { + return false; + } + } + + if (allowList.size() > 0) { + for (IPRange range : allowList) { + if (range.isIPAddressInRange(ipAddress)) { + return true; + } + } + + return false; + } + + return true; + } + + public void service(HttpServletRequest request + , HttpServletResponse response + , String servletPath + , ProcessCallback processCallback + ) throws ServletException, IOException { + String contextPath = request.getContextPath(); + String requestURI = request.getRequestURI(); + + response.setCharacterEncoding("utf-8"); + + if (contextPath == null) { // root context + contextPath = ""; + } + String uri = contextPath + servletPath; + String path = requestURI.substring(contextPath.length() + servletPath.length()); + + if (!isPermittedRequest(request)) { + path = "/nopermit.html"; + returnResourceFile(path, uri, response); + return; + } + + if ("/submitLogin".equals(path)) { + String usernameParam = request.getParameter(PARAM_NAME_USERNAME); + String passwordParam = request.getParameter(PARAM_NAME_PASSWORD); + if (username.equals(usernameParam) && password.equals(passwordParam)) { + request.getSession().setAttribute(SESSION_USER_KEY, username); + response.getWriter().print("success"); + } else { + response.getWriter().print("error"); + } + return; + } + + if (isRequireAuth() // + && !containsUser(request)// + && !checkLoginParam(request)// + && !("/login.html".equals(path) // + || path.startsWith("/css")// + || path.startsWith("/js") // + || path.startsWith("/img"))) { + if (contextPath.equals("") || contextPath.equals("/")) { + response.sendRedirect("/druid/login.html"); + } else { + if ("".equals(path)) { + response.sendRedirect("druid/login.html"); + } else { + response.sendRedirect("login.html"); + } + } + return; + } + + if ("".equals(path) || "/".equals(path)) { + returnResourceFile("/index.html", uri, response); + return; + } + + if (path.contains(".json")) { + String fullUrl = path; + if (request.getQueryString() != null && request.getQueryString().length() > 0) { + fullUrl += "?" + request.getQueryString(); + } + response.getWriter().print(processCallback.process(fullUrl)); + return; + } + + // find file in resources path + + returnResourceFile(path, uri, response); + } + + + } } diff --git a/src/main/java/com/alibaba/druid/support/http/StatViewFilter.java b/src/main/java/com/alibaba/druid/support/http/StatViewFilter.java index 8d1cfe75f4..38edb58640 100644 --- a/src/main/java/com/alibaba/druid/support/http/StatViewFilter.java +++ b/src/main/java/com/alibaba/druid/support/http/StatViewFilter.java @@ -15,39 +15,117 @@ */ package com.alibaba.druid.support.http; +import com.alibaba.druid.stat.DruidStatService; +import com.alibaba.druid.support.http.util.IPRange; +import com.alibaba.druid.support.logging.Log; +import com.alibaba.druid.support.logging.LogFactory; +import com.alibaba.druid.util.StringUtils; + +import javax.servlet.*; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; import java.io.IOException; -import javax.servlet.Filter; -import javax.servlet.FilterChain; -import javax.servlet.FilterConfig; -import javax.servlet.RequestDispatcher; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; +import static com.alibaba.druid.support.http.ResourceServlet.*; public class StatViewFilter implements Filter { - public final static String PARAM_NAME_PATH = "path"; - private String path = "/druid"; + public final static String PARAM_NAME_PATH = "path"; + private final static Log LOG = LogFactory.getLog(StatViewFilter.class); + private String servletPath = "/druid"; + private String resourcePath = "support/http/resources"; + + private ResourceHandler handler; + private DruidStatService statService = DruidStatService.getInstance(); @Override public void init(FilterConfig config) throws ServletException { + if (config == null) { + return; + } + String path = config.getInitParameter(PARAM_NAME_PATH); if (path != null && !path.isEmpty()) { - this.path = path; + this.servletPath = path; + } + + handler = new ResourceHandler(resourcePath); + + String paramUserName = config.getInitParameter(PARAM_NAME_USERNAME); + if (!StringUtils.isEmpty(paramUserName)) { + handler.username = paramUserName; + } + + String paramPassword = config.getInitParameter(PARAM_NAME_PASSWORD); + if (!StringUtils.isEmpty(paramPassword)) { + handler.password = paramPassword; + } + + String paramRemoteAddressHeader = config.getInitParameter(PARAM_REMOTE_ADDR); + if (!StringUtils.isEmpty(paramRemoteAddressHeader)) { + handler.remoteAddressHeader = paramRemoteAddressHeader; + } + + try { + String param = config.getInitParameter(PARAM_NAME_ALLOW); + if (param != null && param.trim().length() != 0) { + param = param.trim(); + String[] items = param.split(","); + + for (String item : items) { + if (item == null || item.length() == 0) { + continue; + } + + IPRange ipRange = new IPRange(item); + handler.allowList.add(ipRange); + } + } + } catch (Exception e) { + String msg = "initParameter config error, allow : " + config.getInitParameter(PARAM_NAME_ALLOW); + LOG.error(msg, e); + } + + try { + String param = config.getInitParameter(PARAM_NAME_DENY); + if (param != null && param.trim().length() != 0) { + param = param.trim(); + String[] items = param.split(","); + + for (String item : items) { + if (item == null || item.length() == 0) { + continue; + } + + IPRange ipRange = new IPRange(item); + handler.denyList.add(ipRange); + } + } + } catch (Exception e) { + String msg = "initParameter config error, deny : " + config.getInitParameter(PARAM_NAME_DENY); + LOG.error(msg, e); } } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest httpReq = (HttpServletRequest) request; - String uri = httpReq.getRequestURI(); - if (uri.startsWith(path)) { - RequestDispatcher dispatcher = request.getRequestDispatcher(httpReq.getServletPath()); - dispatcher.forward(request, response); - } else { - chain.doFilter(request, response); + HttpServletResponse httpResp = (HttpServletResponse) response; + String contextPath = ((HttpServletRequest) request).getContextPath(); + + String requestURI = httpReq.getRequestURI(); + if (!contextPath.equals("")) { + requestURI = requestURI.substring(((HttpServletRequest) request).getContextPath().length()); } + if (requestURI.equals(servletPath)) { + httpResp.sendRedirect(httpReq.getRequestURI() + '/'); + } + + handler.service(httpReq, httpResp, servletPath, new ResourceServlet.ProcessCallback() { + @Override + public String process(String url) { + return statService.service(url); + } + }); } @Override diff --git a/src/main/java/com/alibaba/druid/support/http/StatViewServlet.java b/src/main/java/com/alibaba/druid/support/http/StatViewServlet.java index 94d9ee0d74..fff7186679 100644 --- a/src/main/java/com/alibaba/druid/support/http/StatViewServlet.java +++ b/src/main/java/com/alibaba/druid/support/http/StatViewServlet.java @@ -25,6 +25,8 @@ import javax.management.remote.JMXConnector; import javax.management.remote.JMXConnectorFactory; import javax.management.remote.JMXServiceURL; import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; import com.alibaba.druid.stat.DruidStatService; import com.alibaba.druid.support.logging.Log; @@ -191,4 +193,34 @@ public class StatViewServlet extends ResourceServlet { return resp; } + public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + String contextPath = request.getContextPath(); + String servletPath = request.getServletPath(); + String requestURI = request.getRequestURI(); + + response.setCharacterEncoding("utf-8"); + + if (contextPath == null) { // root context + contextPath = ""; + } + String uri = contextPath + servletPath; + String path = requestURI.substring(contextPath.length() + servletPath.length()); + + if ("".equals(path)) { + if (contextPath.equals("") || contextPath.equals("/")) { + response.sendRedirect("/druid/index.html"); + } else { + response.sendRedirect("druid/index.html"); + } + return; + } + + if ("/".equals(path)) { + response.sendRedirect("index.html"); + return; + } + + super.service(request, response); + } + }