转:
Druid是一个强大的新兴数据库连接池,兼容DBCP,是阿里巴巴做的开源项目.
不仅提供了强悍的数据源实现,还内置了一个比较靠谱的监控组件。
GitHub项目主页: https://github.com/alibaba/druid
QQ群: 点击链接加入群【阿里开源技术交流】
演示地址: https://cncounter.duapp.com/druid/index.html
常见问题回答请参考: https://github.com/alibaba/druid/wiki/%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98
一篇CSDN对Druid的介绍 druid简单教程
因为想要监控数据,又不愿意谁都可以访问,所以想要配置个密码.在开源群里一问,就知道原来内部已经有实现了.
先贴完成后的代码:
web.xml 部分:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
|
<! -- Druid,监控数据库,以及WEB访问连接信息 -->
<! -- 参考: https://github.com/alibaba/druid/wiki/%E9%85%8D%E7%BD%AE_%E9%85%8D%E7%BD%AEWebStatFilter -->
<filter> <filter- name >DruidWebStatFilter</filter- name >
<filter-class>com.alibaba.druid.support.http.WebStatFilter</filter-class>
<init-param>
<param- name >exclusions</param- name >
<param-value>*.js,*.gif,*.jpg,*.png,*.css,*.ico,*.jsp,/druid/*,/download/*</param-value>
</init-param>
<init-param>
<param- name >sessionStatMaxCount</param- name >
<param-value>2000</param-value>
</init-param>
<init-param>
<param- name >sessionStatEnable</param- name >
<param-value> true </param-value>
</init-param>
<init-param>
<param- name >principalSessionName</param- name >
<param-value>session_user_key</param-value>
</init-param>
<init-param>
<param- name >profileEnable</param- name >
<param-value> true </param-value>
</init-param>
</filter> <filter-mapping> <filter- name >DruidWebStatFilter</filter- name >
<url-pattern>/*</url-pattern>
</filter-mapping> <! -- 配置 Druid 监控信息显示页面 -->
<servlet> <servlet- name >DruidStatView</servlet- name >
<servlet-class>com.alibaba.druid.support.http.StatViewServlet</servlet-class>
<init-param>
<! -- 允许清空统计数据 -->
<param- name >resetEnable</param- name >
<param-value> true </param-value>
</init-param>
<init-param>
<! -- 用户名 -->
<param- name >loginUsername</param- name >
<param-value>druid</param-value>
</init-param>
<init-param>
<! -- 密码 -->
<param- name >loginPassword</param- name >
<param-value>druid</param-value>
</init-param>
</servlet> <servlet-mapping> <servlet- name >DruidStatView</servlet- name >
<url-pattern>/druid/*</url-pattern>
</servlet-mapping> |
首先,因为使用的是 MAVEN, 所以查看源码时maven会自动帮你下载. 我们在 web.xml 中点击 com.alibaba.druid.support.http.StatViewServlet 进入class文件,等一会源码下载好就可以查看. 发现有类似下面这样的代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
public class StatViewServlet extends ResourceSerlvet {
private final static Log LOG = LogFactory.getLog(StatViewServlet.class);
private static final long serialVersionUID = 1L;
public static final String PARAM_NAME_RESET_ENABLE = "resetEnable" ;
public static final String PARAM_NAME_JMX_URL = "jmxUrl" ;
public static final String PARAM_NAME_JMX_USERNAME = "jmxUsername" ;
public static final String PARAM_NAME_JMX_PASSWORD = "jmxPassword" ;
private DruidStatService statService = DruidStatService.getInstance();
/** web.xml中配置的jmx的连接地址 */
private String jmxUrl = null ;
/** web.xml中配置的jmx的用户名 */
private String jmxUsername = null ;
/** web.xml中配置的jmx的密码 */
private String jmxPassword = null ;
......... |
StatViewServlet extends ResourceSerlvet
而在其中的 jmxUrl、jmxUsername 和 jmxPassword 很显然是连接远程 JMX时使用的,那么我就想着去看看父类: com.alibaba.druid.support.http.ResourceSerlvet
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
@SuppressWarnings( "serial" )
public abstract class ResourceSerlvet extends HttpServlet {
private final static Log LOG = LogFactory.getLog(ResourceSerlvet.class);
public static final String SESSION_USER_KEY = "druid-user" ;
public static final String PARAM_NAME_USERNAME = "loginUsername" ;
public static final String PARAM_NAME_PASSWORD = "loginPassword" ;
public static final String PARAM_NAME_ALLOW = "allow" ;
public static final String PARAM_NAME_DENY = "deny" ;
public static final String PARAM_REMOTE_ADDR = "remoteAddress" ;
protected String username = null ;
protected String password = null ;
.......... |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
......
if (isRequireAuth() //
&& !ContainsUser(request)//
&& !( "/login.html" .equals(path) //
|| path.startsWith( "/css" )//
|| path.startsWith( "/js" ) //
|| path.startsWith( "/img" ))) {
if (contextPath == null || contextPath.equals( "" ) || contextPath.equals( "/" )) {
response.sendRedirect( "/druid/login.html" );
} else {
if ( "" .equals(path)) {
response.sendRedirect( "druid/login.html" );
} else {
response.sendRedirect( "login.html" );
}
}
return ;
}
...... |
isRequireAuth() 方法,看着像是判断是否需要授权验证,于是进去看
1
2
3
|
public boolean isRequireAuth() {
return this.username != null ;
} |
那现在知道是 username 在作怪,也设置了,但是没有起作用,于是搜索 username ,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
public void init() throws ServletException {
initAuthEnv();
} private void initAuthEnv() { String paramUserName = getInitParameter(PARAM_NAME_USERNAME);
if (!StringUtils.isEmpty(paramUserName)) {
this.username = paramUserName;
}
String paramPassword = getInitParameter(PARAM_NAME_PASSWORD);
if (!StringUtils.isEmpty(paramPassword)) {
this. password = paramPassword;
}
......
|
然后发现了初始化验证环境时使用了PARAM_NAME_USERNAME这个参数,顺便的学习了一个新API: getInitParameter 方法获取 Servlet的初始化参数, 是HttpServlet的父类 GenericServlet 类提供的:
String paramUserName = getInitParameter(PARAM_NAME_USERNAME);
那么很简单,找到 PARAM_NAME_USERNAME 即可:
public static final String PARAM_NAME_USERNAME = "loginUsername"; public static final String PARAM_NAME_PASSWORD = "loginPassword";
于是在 web.xml 中换上,OK,成功进行了拦截.