一種基於annotation的Spring-mvc權限控制方法

##簡介## 本文介紹一種採用annotation來對spring-mvc進行權限控制的方法. 經過枚舉類來定義權限項. 將annotation標註到須要控制權限的spring-mvc方法上. 而後,在spring-mvc中定義全局過濾器, 過濾全部spring-mvc方法, 查看方法上的權限annotation信息, 以此對權限進行控制.
程序源代碼: https://github.com/eagle0445/sample/html

##優勢## 編寫比較方便, 在須要控制權限的方法上進行annotation的標註便可, ide可以對annotation進行識別支持. 查看權限配置比較方便, 由於annotation就在方法上, 不用去其餘地方翻看. 實現方式比較簡單.java

##具體實現##mysql

###1.創建權限枚舉類### 創建權限枚舉類型, 用於描述權限的種類, 包含了權限的名稱. 每一個枚舉值中包含了權限中文名稱和權限索引值(即權限位). (思考:是否能夠直接用中文名稱做爲枚舉值的名稱,我在其餘程序已經用了中文枚舉名稱了,暫時沒有遇到問題)git

<!-- lang: java -->
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的登陸github

<!-- lang: java -->
public enum ResultTypeEnum {
//整頁刷新
page, 
//json數據
json
}

###3.創建表示權限annotation類### 創建annotation類, 用於標註到須要權限驗證的地方web

<!-- lang: java -->
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便可.ajax

<!-- lang: sql -->
    create table user (
        id integer not null auto_increment,
		name varchar(255),
        right_content varchar(255),
        primary key (id)
    ) type=InnoDB

###5.權限驗證算法### 權限判斷方法, 權限判斷的實現算法, 用於判斷是否有權限算法

<!-- lang: java -->
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類, 用於過濾須要控制權限的方法.spring

<!-- lang: java -->
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, 實現過濾.sql

<!-- lang: xml -->
    <mvc:interceptors>
		<bean class="interceptor.AuthorityAnnotationInterceptor"></bean>
	</mvc:interceptors>

###8.標註須要控制權限的方法### 在須要控制訪問的spring-mvc方法上面加上對應的標註.
//方式一

<!-- lang: java -->
@FireAuthority(AuthorityType. SALES_ORDER_CREATE)
@RequestMapping(value="/save.spr", method=RequestMethod.POST)
public ModelAndView save(String  name) throws Exception {
    //some code
}

//方式二

<!-- lang: java -->
@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
	}

//方式三

<!-- lang: java -->
@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.完成了### ^_^

##後續## 還須要一套界面,以便進行用戶權限的配置, 幸運的是本人已經實現了這一功能, 而代碼相對比較簡單, 將在後面的博客中進行詳細解說.
程序源代碼: https://github.com/eagle0445/sample/

相關文章
相關標籤/搜索