【Shiro許可權管理】17.Shiro許可權註解
阿新 • • 發佈:2019-02-06
注:該系列所有測試均在之前建立的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:
然後將這個Service注入Spring的IOC容器,即在applicationContext.xml中新增該Service對應的bean:
然後在原來的登入Controller中注入該Service,並建立一個testShiroAnnocation服務:
在list.jsp介面新增一個觸發“testShiroAnnocation”服務的超連結:
此時我們沒有給testShiroAnnocation服務加任何許可權註解,所以是可以自由訪問的:
點選超連結之後,MyEclipse的控制檯顯示了執行方法的時間:
下面我們對Service的testMethod方法新增一個控制權限的註解“@RequiresRoles”:
下面我們使用沒有admin角色的jack使用者登入:
然後點選“Test ShiroAnnocation”超連結時,沒有顯示執行方法時間,而是丟擲了異常:
改異常表明了使用者沒有“admin”的角色資訊。
上面的異常可以使用Spring的“宣告式異常”來跳轉至友好提示頁面,這裡就不進行處理了。
最後需要注意的是:
在日常開發時,往往會在Service層新增“@Transactional”註解,為的是當Service傳送資料庫異常時,
所有資料庫操作可以回滾。
當在Service層新增“@Transactional”註解後,執行Service方法前,會開啟事務。此時的Service已經是
一個代理物件了,此時如果我們將Shiro的許可權註解載入Service層是不合適的,此時需要加到Controller
層。這是因為不能讓Service是“代理的代理”,如果強行注入,會發生型別轉換異常。
前面我們講解了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:
在其中編寫了名為“testMethod”的方法,在其中列印呼叫方法的當前時間。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())); } }
然後將這個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">登出</a>
<br/><br/>
<!-- “testShiroAnnocation”服務的超連結 -->
<a href="userAuth/testShiroAnnocation">Test ShiroAnnocation</a>
<shiro:hasRole name="admin">
<br/><br/>
<a href="admin.jsp">Admin Page</a>
</shiro:hasRole>
<shiro:hasRole name="user">
<br/><br/>
<a href="User.jsp">User Page</a>
</shiro:hasRole>
</body>
</html>
此時我們沒有給testShiroAnnocation服務加任何許可權註解,所以是可以自由訪問的:
點選超連結之後,MyEclipse的控制檯顯示了執行方法的時間:
下面我們對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使用者登入:
然後點選“Test ShiroAnnocation”超連結時,沒有顯示執行方法時間,而是丟擲了異常:
改異常表明了使用者沒有“admin”的角色資訊。
上面的異常可以使用Spring的“宣告式異常”來跳轉至友好提示頁面,這裡就不進行處理了。
最後需要注意的是:
在日常開發時,往往會在Service層新增“@Transactional”註解,為的是當Service傳送資料庫異常時,
所有資料庫操作可以回滾。
當在Service層新增“@Transactional”註解後,執行Service方法前,會開啟事務。此時的Service已經是
一個代理物件了,此時如果我們將Shiro的許可權註解載入Service層是不合適的,此時需要加到Controller
層。這是因為不能讓Service是“代理的代理”,如果強行注入,會發生型別轉換異常。
以上就是關於Shiro許可權註解的講解。