天天看點

【Shiro權限管理】17.Shiro權限注解

注:該系列所有測試均在之前建立的Shiro3的Web工程的基礎上。

前面我們講解了Shiro的标簽屬性,下面我們來講解Shiro的有關權限的注解屬性。

Shiro的注解是使用在相應的Java類的方法上,當使用者不滿足注解的要求時,是無法執行

方法内部邏輯的。這相當于在代碼層做了權限校驗。

Shiro的注解可以放置在Controller層對應的方法上,也可以放置在Service層對應的方法上。

Shiro的注解類型大緻如下:

(1) @RequiresAuthentication

表示目前Subject已經通過login進行了身份驗證;即Subject.isAuthenticated()傳回true。

(2) @RequiresUser

表示目前Subject已經進行身份驗證或者通過“記住我”登入。

(3) @RequiresGuest

表示目前Subject沒有身份驗證或者通過“記住我”登入過,即是 遊客身份。

(4) @RequiresRoles(value={"admin","user"},logical=Logical.OR)

表示目前Subject需要角色admin和user。

(5) @RequiresPermissions(value={"user:a","user:b"},logical=Logical.OR)

表示目前Subject需要權限user:a或user:b。

下面我們在原來Shiro3工程的基礎上測試幾個注解。

首先在工程中建立一個Service:

package com.test.shiro.services;
import java.text.SimpleDateFormat;
import java.util.Date;
public class ShiroService {
    public void testMethod(){
    	System.out.println("testMethod,time:"
    			+new SimpleDateFormat("yyy-MM-dd HH:mm:ss").format(new  Date()));
    }
}
           

在其中編寫了名為“testMethod”的方法,在其中列印調用方法的目前時間。

然後将這個Service注入Spring的IOC容器,即在applicationContext.xml中添加該Service對應的bean:

<bean id="shiroService" class="com.test.shiro.services.ShiroService">
</bean>
           

然後在原來的登入Controller中注入該Service,并建立一個testShiroAnnocation服務:

package com.test.shiro.controller;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import com.test.shiro.services.ShiroService;

@Controller
@RequestMapping("userAuth")
public class ShiroLoginController {
	
	@Autowired
	private ShiroService shiroService;
	
	@RequestMapping("/testShiroAnnocation")
	private String testShiroAnnocation(){
		shiroService.testMethod();
		return "redirect:/list.jsp";
	}
	
	@RequestMapping("login")
	public String login(String username,String password){
		//擷取目前的Subject
        	Subject currentUser = SecurityUtils.getSubject();
        	//測試目前使用者是否已經被認證(即是否已經登入)
        	if (!currentUser.isAuthenticated()) {
        		//将使用者名與密碼封裝為UsernamePasswordToken對象
            		UsernamePasswordToken token = 
				new UsernamePasswordToken(username, password);
            		token.setRememberMe(true);//記錄使用者
            		try {
                		currentUser.login(token);//調用Subject的login方法執行登入
            		} catch (AuthenticationException e) {//所有認證時異常的父類
                		System.out.println("登入失敗:"+e.getMessage());
            		} 
        	}
		return "redirect:/list.jsp";
	}
}
           

在list.jsp界面添加一個觸發“testShiroAnnocation”服務的超連結:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>首頁</title>
  </head>
  <body>
     登入成功!歡迎<shiro:principal/>通路首頁O(∩_∩)O
   <a href="userAuth/logout" target="_blank" rel="external nofollow" >登出</a>
   
   <br/><br/>
   <!-- “testShiroAnnocation”服務的超連結 -->
   <a href="userAuth/testShiroAnnocation" target="_blank" rel="external nofollow" >Test ShiroAnnocation</a>
   
   <shiro:hasRole name="admin">
   <br/><br/>
   <a href="admin.jsp" target="_blank" rel="external nofollow" >Admin Page</a>
   </shiro:hasRole>
   
   <shiro:hasRole name="user">
   <br/><br/>
   <a href="User.jsp" target="_blank" rel="external nofollow" >User Page</a>
   </shiro:hasRole>
   
  </body>
</html>
           

此時我們沒有給testShiroAnnocation服務加任何權限注解,是以是可以自由通路的:

【Shiro權限管理】17.Shiro權限注解

點選超連結之後,MyEclipse的控制台顯示了執行方法的時間:

【Shiro權限管理】17.Shiro權限注解

下面我們對Service的testMethod方法添加一個控制權限的注解“@RequiresRoles”:

package com.test.shiro.services;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.apache.shiro.authz.annotation.RequiresRoles;
public class ShiroService {
    @RequiresRoles({"admin"})
    public void testMethod(){
    	System.out.println("testMethod,time:"
    			+new SimpleDateFormat("yyy-MM-dd HH:mm:ss").format(new  Date()));
    }
}
           

上面的注解控制隻有當使用者角色包含“admin”時,才會執行testMethod方法。

下面我們使用沒有admin角色的jack使用者登入:

【Shiro權限管理】17.Shiro權限注解

然後點選“Test ShiroAnnocation”超連結時,沒有顯示執行方法時間,而是抛出了異常:

【Shiro權限管理】17.Shiro權限注解

改異常表明了使用者沒有“admin”的角色資訊。

上面的異常可以使用Spring的“聲明式異常”來跳轉至友好提示頁面,這裡就不進行處理了。

最後需要注意的是:

在日常開發時,往往會在Service層添加“@Transactional”注解,為的是當Service發送資料庫異常時,

所有資料庫操作可以復原。

當在Service層添加“@Transactional”注解後,執行Service方法前,會開啟事務。此時的Service已經是

一個代理對象了,此時如果我們将Shiro的權限注解加載Service層是不合适的,此時需要加到Controller

層。這是因為不能讓Service是“代理的代理”,如果強行注入,會發生類型轉換異常。

以上就是關于Shiro權限注解的講解。

轉載請注明出處:http://blog.csdn.net/acmman/article/details/78765315

繼續閱讀