springmvc 权限设计

转自 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
}

9.完成了

你可能感兴趣的:(springMVC)