一个小小的权限拦截器工具

去年暑假前,就感觉在项目中到处进行权限验证太麻烦了,就想利用暑假的几天做一个可以重复利用的权限过滤器,不但能拦截jsp、action、html,还能拦截其他的css、js、picture等的拦截器。

原文

当时感觉挺容易的,后来开学了一直忙,项目中也没用到这个工具,就一直放着。今天又发现了这个jar包,就发出来,看看有什么反响。

为了可持续利用这个工具包,就将过滤设置放在一个xml文件里面,在过滤器启动时候,读取xml里面的内容,然后拦截页面请求,如果页面请求与xml配置的内容符合,就验证请求是否是合法请求,如果合法进入指定页面,如果不合法进入另外一个页面。

我感觉这样一来,应该能减少大量项目内的权限验证(struts2的权限拦截真是鸡肋。。。自我感觉。。。)

配置

在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
<?xml version="1.0" encoding="UTF-8"?> 
<web-app version="2.5"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

<!-- 自定义用户权限验证 -->
<filter>
<filter-name>QualificationChack</filter-name>
<filter-class>net.henu.sulin.filter.qualification.QualificationFilter</filter-class>
<init-param>
<description>该权限过滤器的配置文件位置,相对于根目录的路径,代码里面就是直接通过“项目根路径+xmlPath”获取配置文件的。。。</description>
<param-name>xmlPath</param-name>
<param-value>WEB-INF/Qualification.xml</param-value>
</init-param>
<init-param>
<description>是否在项目启动时,在控制台打印输出配置信息,可填的值为true/任何东西。此配置参数可以不要</description>
<param-name>showRules</param-name>
<param-value></param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>QualificationChack</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher><!-- 拦截Request请求 -->
<dispatcher>FORWARD</dispatcher><!-- 拦截重定向请求 -->
</filter-mapping>

</web-app>

添加Qualification.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
<?xml version="1.0" encoding="UTF-8"?>
<rules>
<!-- 这个是模板演示(目前不会dtd配置)
<rule>
<url> //配置拦截器将拦截哪些请求,过滤器里面就是直接用请求和配置equals的。。。
<param>/demo.jsp</param> //拦截指定页面的请求
<param>/demo/</param> //拦截指定文件夹的请求
</url>
<access>
<scope>session | request</scope> //拦截的范围,想到的就request和session了。。。
<key>user.name</key> //拦截的key。可以是对象, 也可以是对象的属性 如:user, user.name , obj1.paramObj2.paramObj3.param, 如果是属性必须得有getter方法,
<value>sulin</value> // null表示为空, !null 表示非空,其他值没有特殊含义,不要使用特殊字符
</access>
<errorPage></errorPage> //验证失败进入的页面,比如用户没有登录,则进入登录页面
<to></to> //验证成功进入的页面(默认是用户请求的下一个页面) 已经作废,感觉无用
</rule>
-->
<rule>
<url>
<param>/UserCenter/</param>
<param>/myPosts</param>
<param>/myReplys</param>
</url>
<access>
<scope>session</scope>
<key>currentUser</key>
<value>!null</value>
</access>
<errorPage>/ErrorPage/NotLoginError.html</errorPage>
</rule>
</rules>

QualificationFilter类:

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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
package net.henu.sulin.filter.qualification;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import net.henu.sulin.filter.qualification.Rule;
import net.henu.sulin.filter.qualification.XmlReader;

public class QualificationFilter implements Filter {
private List<Rule> rules = new ArrayList();
private boolean isSuccess = true;

public QualificationFilter() {
}

public void init(FilterConfig filterConfig) throws ServletException {
String RootPath = filterConfig.getServletContext().getRealPath("/");
String filePath = filterConfig.getInitParameter("xmlPath");
String showRules = filterConfig.getInitParameter("showRules");
String xmlFileName = "file:///" + RootPath + filePath;
if("\\".equals(File.separator)) {
xmlFileName = xmlFileName.replaceAll("/", "\\\\");
} else {
xmlFileName = xmlFileName.replaceAll("\\", "/");
}

XmlReader xmlReader = new XmlReader();
this.isSuccess = xmlReader.MainTest(xmlFileName, this.rules);
if("true".equals(showRules)) {
Iterator it = this.rules.iterator();

while(it.hasNext()) {
((Rule)it.next()).ShowRule();
}
}

}

public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest)req;
HttpServletResponse response = (HttpServletResponse)resp;
String currentURL = request.getRequestURI();
if(this.isSuccess) {
Iterator it = this.rules.iterator();

while(it.hasNext()) {
Rule rule = (Rule)it.next();
if(!rule.RuleCheck(currentURL, request)) {
response.sendRedirect(rule.getErrorPage());
return;
}
}
}

chain.doFilter(req, resp);
}

public void destroy() {
}
}

Rule类

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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
package net.henu.sulin.filter.qualification;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Pattern;
import javax.servlet.http.HttpServletRequest;

public class Rule {
private List<String> url = new ArrayList();
private String scope;
private String key;
private String value;
private String errorPage;
private String to;

public Rule() {
}

public List<String> getUrl() {
return this.url;
}

public void setUrl(List<String> url) {
this.url = url;
}

public void addUrl(String urlParam) {
this.url.add(urlParam);
}

public String getScope() {
return this.scope;
}

public void setScope(String scope) {
this.scope = scope;
}

public String getKey() {
return this.key;
}

public void setKey(String key) {
this.key = key;
}

public String getErrorPage() {
return this.errorPage;
}

public void setErrorPage(String errorPage) {
this.errorPage = errorPage;
}

public String getTo() {
return this.to;
}

public void setTo(String to) {
this.to = to;
}

public void setValue(String value) {
this.value = value;
}

public String getValue() {
return this.value;
}

public void ShowRule() {
System.out.print("\n----------------------------------------------------------");
System.out.print("\n拦截页面: ");
Iterator it = this.url.iterator();

while(it.hasNext()) {
System.out.print(" [" + (String)it.next() + "] ");
}

System.out.print("\n拦截Scope: " + this.scope);
System.out.print("\n拦截key: " + this.key);
System.out.print("\n拦截value: " + this.value);
System.out.print("\n错误页面errorPage: " + this.errorPage);
System.out.print("\n----------------------------------------------------------\n\n");
}

public boolean RuleCheck(String url, HttpServletRequest request) {
boolean isIntoRule = false;
Iterator keys = this.url.iterator();

while(keys.hasNext()) {
String resultObj = (String)keys.next();
if(url.startsWith(resultObj)) {
System.out.println("进入规则");
isIntoRule = true;
break;
}
}

if(isIntoRule) {
String[] var14 = this.key.split(Pattern.quote("."));
Object var15 = null;
if("session".equals(this.scope)) {
var15 = request.getSession().getAttribute(var14[0]);
}

if("request".equals(this.scope)) {
var15 = request.getAttribute(var14[0]);
}

for(int i = 1; i < var14.length; ++i) {
if(var15 == null) {
return false;
}

Method method = null;

try {
method = var15.getClass().getDeclaredMethod(this.getGetMethodName(var14[i]), new Class[]{null});
} catch (SecurityException var12) {
System.out.println(var14[i] + "的getter方法不是public类型的, 权限过滤无法实现");
return true;
} catch (NoSuchMethodException var13) {
System.out.println(var14[i] + "的无参getter方法不存在, 权限过滤无法实现");
return true;
}

try {
var15 = method.invoke(var15, (Object[])null);
} catch (IllegalArgumentException var9) {
System.out.println(var14[i] + "的无参getter方法不存在, 权限过滤无法实现");
return true;
} catch (IllegalAccessException var10) {
System.out.println(var14[i] + "的无参getter方法不是public类型的, 权限过滤无法实现");
return true;
} catch (InvocationTargetException var11) {
System.out.println("权限过滤器调用" + var14[i] + "的getter方法时候,出现以下异常, 权限过滤无法实现:");
var11.printStackTrace();
return true;
}
}

if(var15 == null) {
if("null".equals(this.value)) {
return true;
}

return false;
}

if(var15 != null) {
if("null".equals(this.value)) {
return false;
}

if("!null".equals(this.value)) {
return true;
}

if(this.value.equals(var15)) {
return true;
}

return false;
}
}

return true;
}

public String getGetMethodName(String name) {
return "get" + name.substring(0, 1).toUpperCase() + name.substring(1);
}
}

XmlReader类实现:

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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
package net.henu.sulin.filter.qualification;

import java.io.IOException;
import java.util.List;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import net.henu.sulin.filter.qualification.Rule;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public class XmlReader {
public XmlReader() {
}

public boolean MainTest(String xmlFileName, List<Rule> rules) {
boolean result = true;
String filename = xmlFileName;
Document document = this.newDocument(xmlFileName);
if(document == null) {
return false;
} else {
NodeList nodeList = document.getElementsByTagName("rule");
if(nodeList.getLength() == 0) {
System.out.println("警告: [" + xmlFileName + "] 中的rule节点为空, 该过滤器无效");
return false;
} else {
for(int i = 0; i < nodeList.getLength(); ++i) {
Rule rule = new Rule();
Node ruleNode = nodeList.item(i);
NodeList urlList = ruleNode.getOwnerDocument().getElementsByTagName("url");
if(urlList.getLength() == 1) {
Node accessNodeList = urlList.item(0);
NodeList accessNode = accessNodeList.getOwnerDocument().getElementsByTagName("param");

Node scopeNode;
String keyNodeList;
for(int scopeNodeList = 0; scopeNodeList < accessNode.getLength(); ++scopeNodeList) {
scopeNode = accessNode.item(scopeNodeList);
if(this.IsFinishNode(scopeNode)) {
keyNodeList = scopeNode.getFirstChild().getNodeValue().trim();
if(!keyNodeList.startsWith("/")) {
System.out.println("警告: [" + filename + "] 中的第" + (i + 1) + "个rule节点下的url参数[" + keyNodeList + "]不是以\'/\'为开始的字符串, 该param配置可能无效");
}

rule.addUrl(keyNodeList);
} else {
System.out.println("警告: [" + filename + "] 中的第" + (i + 1) + "个rule节点下的url节点下的第" + (scopeNodeList + 1) + "个parma节点非法{该节点不是一个根节点}, 该param配置被抛弃");
}
}

NodeList var22 = ruleNode.getOwnerDocument().getElementsByTagName("access");
if(var22.getLength() != 1) {
System.out.println("严重: [" + filename + "] 中的第" + (i + 1) + "个rule节点下没有必需的access节点或access节点不止一个,该rule配置被抛弃");
} else {
Node var23 = var22.item(0);
NodeList var24 = var23.getOwnerDocument().getElementsByTagName("scope");
if(var24.getLength() != 1) {
System.out.println("严重: [" + filename + "] 中的第" + (i + 1) + "个rule节点的access节点下没有必需的scope节点或scope节点不止一个,该rule配置被抛弃");
} else {
scopeNode = var24.item(0);
if(this.IsFinishNode(scopeNode)) {
keyNodeList = scopeNode.getFirstChild().getNodeValue();
if(!keyNodeList.equals("session") && !keyNodeList.equals("request") && !keyNodeList.equals("response")) {
System.out.println("严重: [" + filename + "] 中的第" + (i + 1) + "个rule节点的access节点下的scope值[" + keyNodeList + "]不会被拦截器拦截,该rule配置被抛弃");
} else {
rule.setScope(keyNodeList);
NodeList var25 = var23.getOwnerDocument().getElementsByTagName("key");
if(var25.getLength() != 1) {
System.out.println("严重: [" + filename + "] 中的第" + (i + 1) + "个rule节点的access节点下没有必需的key节点或key节点不止一个,该rule配置被抛弃");
} else {
Node keyNode = var25.item(0);
if(this.IsFinishNode(keyNode)) {
String valueNodeList = keyNode.getFirstChild().getNodeValue();
rule.setKey(valueNodeList);
NodeList var26 = var23.getOwnerDocument().getElementsByTagName("value");
if(var26.getLength() != 1) {
System.out.println("严重: [" + filename + "] 中的第" + (i + 1) + "个rule节点的access节点下没有必需的value节点或value节点不止一个,该rule配置被抛弃");
} else {
Node valueNode = var26.item(0);
if(this.IsFinishNode(valueNode)) {
String errorPageNodeList = valueNode.getFirstChild().getNodeValue();
rule.setValue(errorPageNodeList);
NodeList var27 = ruleNode.getOwnerDocument().getElementsByTagName("errorPage");
if(var27.getLength() != 1) {
System.out.println("严重: [" + filename + "] 中的第" + (i + 1) + "个rule节下没有必需的errorPage节点或errorPage节点不止一个,该rule配置被抛弃");
} else {
Node errorPageNode = var27.item(0);
if(this.IsFinishNode(errorPageNode)) {
String errorPage = errorPageNode.getFirstChild().getNodeValue();
if(!errorPage.startsWith("/")) {
System.out.println("警告: [" + filename + "] 中的第" + (i + 1) + "个rule节点下的errorPage参数[" + errorPage + "]不是以\'/\'为开始的字符串, 该param配置可能无效");
}

rule.setErrorPage(errorPage);
rules.add(rule);
} else {
System.out.println("严重: [" + filename + "] 中的第" + (i + 1) + "个rule节点的access节点下的value节点非法{不是根节点},该rule配置被抛弃");
}
}
} else {
System.out.println("严重: [" + filename + "] 中的第" + (i + 1) + "个rule节点的access节点下的value节点非法{不是根节点},该rule配置被抛弃");
}
}
} else {
System.out.println("严重: [" + filename + "] 中的第" + (i + 1) + "个rule节点的access节点下的key节点非法{不是根节点},该rule配置被抛弃");
}
}
}
} else {
System.out.println("严重: [" + filename + "] 中的第" + (i + 1) + "个rule节点的access节点下的scope节点非法{不是根节点},该rule配置被抛弃");
}
}
}
} else {
System.out.println("严重: [" + filename + "] 中的第" + (i + 1) + "个rule节点下没有必需的url节点或url节点不止一个,该rule配置被抛弃");
}
}

return result;
}
}
}

public Document newDocument(String filename) {
DocumentBuilder documentBuilder = null;

try {
documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
} catch (ParserConfigurationException var7) {
var7.printStackTrace();
System.out.println("严重: W3CReader无法完成初始化, 由于系统无法创建满足所请求配置的 DocumentBuilder");
return null;
}

Document document = null;

try {
document = documentBuilder.parse(filename);
return document;
} catch (SAXException var5) {
var5.printStackTrace();
System.out.println("严重: W3CReader无法完成初始化, 由于DocumentBuilder解析外部xml文件[" + filename + "]时出现解析错误, 请检查是否有语法错误");
return null;
} catch (IOException var6) {
var6.printStackTrace();
System.out.println("严重: W3CReader无法完成初始化, 由于DocumentBuilder解析外部xml文件[" + filename + "]时出现IO错误,请检查文件是否存在且有效");
return null;
}
}

public boolean IsFinishNode(Node node) {
boolean result = false;
if(node instanceof Element && node.getChildNodes().getLength() == 1 && !(node.getFirstChild() instanceof Element)) {
result = true;
}

return result;
}
}

2015年回顾

当年青涩的自己还真是任性,代码写的如此销魂。。。