转自 http://www.open-open.com/lib/view/open1358472021196.html
简介
本文介绍一种采用annotation来对spring-mvc进行权限控制的方法. 通过枚举类来定义权限项. 将annotation标注到需要控制权限的spring-mvc方法上. 然后,在spring-mvc中定义全局过滤器, 过滤所有spring-mvc方法, 查看方法上的权限annotation信息, 以此对权限进行控制.
优点
编写比较方便, 在需要控制权限的方法上进行annotation的标注即可, ide能够对annotation进行识别支持. 查看权限配置比较方便, 因为annotation就在方法上, 不用去其他地方翻看. 实现方式比较简单.
具体实现
1.建立权限枚举类
建立权限枚举类型, 用于描述权限的种类, 包含了权限的名称. 每个枚举值中包含了权限中文名称和权限索引值(即权限位). (思考:是否可以直接用中文名称作为枚举值的名称,我在其他程序已经用了中文枚举名称了,暂时没有遇到问题)
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
|
public
enum
AuthorityType{
// 包含了枚举的中文名称, 枚举的索引值
WORKER(
"增删改查员工"
,
1
),
SALES_ORDER_CREATE(
"创建订单"
,
6
),
SALES_ORDER_FIND(
"查看订单"
,
7
),
SALES_ORDER_MODIFY(
"修改订单"
,
8
),
SALES_ORDER_DELETE(
"删除订单"
,
9
),
;
private
String name;
private
int
index;
private
AuthorityType(String name,
int
index) {
this
.name = name;
this
.index = index;
}
public
String getName() {
return
name;
}
public
void
setName(String name) {
this
.name = name;
}
public
int
getIndex() {
return
index;
}
public
void
setIndex(
int
index) {
this
.index = index;
}
}
|
2.登录方式的枚举类
登录方式的枚举类, page代表传统登录页面, json表示ajax的登录
1
2
3
4
5
6
|
public
enum
ResultTypeEnum {
//整页刷新
page,
//json数据
json
}
|
3.建立表示权限annotation类
建立annotation类, 用于标注到需要权限验证的地方
1
2
3
4
5
6
7
8
9
10
11
12
13
|
import
java.lang.annotation.Documented;
import
java.lang.annotation.ElementType;
import
java.lang.annotation.Retention;
import
java.lang.annotation.RetentionPolicy;
import
java.lang.annotation.Target;
@Target
(ElementType.METHOD)
@Retention
(RetentionPolicy.RUNTIME)
@Documented
public
@interface
FireAuthority {
AuthorityType[] authorityTypes();
ResultTypeEnum resultType()
default
ResultTypeEnum.page;
}
|
4.在user类中加入权限字段
在user用户类中添加文本字段表示权限, 字段长度为250字符(因为mysql默认255个字符,可以代表250个权限应该够用了), 字符内容是0或者1. 1表示有权限, 0表示无权限. 提示: 对于用户的权限配置, 只要将对应的权限位设置为0或者1即可.
1
2
3
4
5
6
|
create
table
user
(
id
integer
not
null
auto_increment,
name
varchar
(255),
right_content
varchar
(255),
primary
key
(id)
) type=InnoDB
|
5.权限验证算法
权限判断方法, 权限判断的实现算法, 用于判断是否有权限
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
public
class
AuthorityHelper {
/**
* 判断是否有权限
* @param akey aString中位置的索引值,也就是权限位
* @param aString 权限字段,比如 11010101011101
* @return
*/
public
static
boolean
hasAuthority(
int
akey,String aString){
return
ConstanHelper.getAuthorityVaule(akey,rc);
if
(aString==
null
||
""
.equals(aString)){
return
false
;
}
char
value = aString.charAt(akey);
if
(value ==
'1'
){
return
true
;
}
return
false
;
}
}
|
6.建立控制权限的interceptor类
建立interceptor类, 用于过滤需要控制权限的方法.
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
|
import
java.io.OutputStream;
import
java.io.OutputStreamWriter;
import
java.io.PrintWriter;
import
java.net.URLEncoder;
import
javax.servlet.http.HttpServletRequest;
import
javax.servlet.http.HttpServletResponse;
import
javax.servlet.http.HttpSession;
import
org.slf4j.Logger;
import
org.slf4j.LoggerFactory;
import
org.springframework.web.method.HandlerMethod;
import
org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
public
class
AuthorityAnnotationInterceptor
extends
HandlerInterceptorAdapter {
final
Logger logger = LoggerFactory.getLogger(getClass());
@Override
public
boolean
preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws
Exception {
logger.debug(
""
);
HandlerMethod handler2=(HandlerMethod) handler;
FireAuthority fireAuthority = handler2.getMethodAnnotation(FireAuthority.
class
);
if
(
null
== fireAuthority){
//没有声明权限,放行
return
true
;
}
logger.debug(
"fireAuthority"
, fireAuthority.toString());
HttpSession session = request.getSession();
Worker manager = (Worker)session.getAttribute(SessionHelper.WorkerHandler);
boolean
aflag =
false
;
for
(AuthorityType at:fireAuthority.authorityTypes()){
if
(AuthorityHelper.hasAuthority(at.getIndex(), manager.getRightContent())==
true
){
aflag =
true
;
break
;
}
}
if
(
false
== aflag){
if
(fireAuthority.resultType() == ResultTypeEnum.page) {
//传统的登录页面
StringBuilder sb =
new
StringBuilder();
sb.append(request.getContextPath());
sb.append(
"/oprst.jsp?oprst=false&opmsg="
).append(URLEncoder.encode(ControllerProperty.NOT_HAVE_AUTHORITY,
"utf-8"
));
response.sendRedirect(sb.toString());
}
else
if
(fireAuthority.resultType() == ResultTypeEnum.json) {
//ajax类型的登录提示
response.setCharacterEncoding(
"utf-8"
);
response.setContentType(
"text/html;charset=UTF-8"
);
OutputStream out = response.getOutputStream();
PrintWriter pw =
new
PrintWriter(
new
OutputStreamWriter(out,
"utf-8"
));
pw.println(
"{\"result\":false,\"code\":12,\"errorMessage\":\""
+ControllerProperty.NOT_HAVE_AUTHORITY+
"\"}"
);
pw.flush();
pw.close();
}
return
false
;
}
return
true
;
}
}
|
7.配置interceptor类
在spring-mvc中配置interceptor, 实现过滤.
1
2
3
|
<
mvc:interceptors
>
<
bean
class
=
"interceptor.AuthorityAnnotationInterceptor"
></
bean
>
</
mvc:interceptors
>
|
8.标注需要控制权限的方法
在需要控制访问的spring-mvc方法上面加上对应的标注.
//方式一
1
2
3
4
5
|
@FireAuthority
(AuthorityType. SALES_ORDER_CREATE)
@RequestMapping
(value=
"/save.spr"
, method=RequestMethod.POST)
public
ModelAndView save(String name)
throws
Exception {
//some code
}
|
//方式二
1
2
3
4
5
|
@FireAuthority
(authorityTypes = {AuthorityType.SALES_ORDER_DELETE,AuthorityType.SALES_ORDER_CREATE})
@RequestMapping
(value=
"/save.spr"
, method=RequestMethod.POST)
public
ModelAndView save(String name)
throws
Exception {
//some code
}
|
//方式三
1
2
3
4
5
|
@FireAuthority
(authorityTypes = AuthorityType.SALES_ORDER_DELETE, resultType=ResultTypeEnum.page)
@RequestMapping
(value=
"/save.spr"
, method=RequestMethod.POST)
public
ModelAndView save(String name)
throws
Exception {
//some code
}
|