java技術研究

          統(tǒng)計

          留言簿(3)

          閱讀排行榜

          評論排行榜

          Apache Shiro 使用手冊(三)Shiro 授權(轉)

          博客分類: 
        1. 開發(fā)

        2. 安全框架Shiro 
          授權即訪問控制,它將判斷用戶在應用程序中對資源是否擁有相應的訪問權限。 
          如,判斷一個用戶有查看頁面的權限,編輯數(shù)據(jù)的權限,擁有某一按鈕的權限,以及是否擁有打印的權限等等。 

          一、授權的三要素 

          授權有著三個核心元素:權限、角色和用戶。 

          權限 
          權限是Apache Shiro安全機制最核心的元素。它在應用程序中明確聲明了被允許的行為和表現(xiàn)。一個格式良好好的權限聲明可以清晰表達出用戶對該資源擁有的權限。 
          大多數(shù)的資源會支持典型的CRUD操作(create,read,update,delete),但是任何操作建立在特定的資源上才是有意義的。因此,權限聲明的根本思想就是建立在資源以及操作上。 
          而我們通過權限聲明僅僅能了解這個權限可以在應用程序中做些什么,而不能確定誰擁有此權限。 
          于是,我們就需要在應用程序中對用戶和權限建立關聯(lián)。 
          通常的做法就是將權限分配給某個角色,然后將這個角色關聯(lián)一個或多個用戶。 

          權限聲明及粒度 
          Shiro權限聲明通常是使用以冒號分隔的表達式。就像前文所講,一個權限表達式可以清晰的指定資源類型,允許的操作,可訪問的數(shù)據(jù)。同時,Shiro權限表達式支持簡單的通配符,可以更加靈活的進行權限設置。 
          下面以實例來說明權限表達式。 
          可查詢用戶數(shù)據(jù) 
          User:view 
          可查詢或編輯用戶數(shù)據(jù) 
          User:view,edit 
          可對用戶數(shù)據(jù)進行所有操作 
          User:* 或 user 
          可編輯id為123的用戶數(shù)據(jù) 
          User:edit:123 

          角色 
          Shiro支持兩種角色模式: 
          1、傳統(tǒng)角色:一個角色代表著一系列的操作,當需要對某一操作進行授權驗證時,只需判斷是否是該角色即可。這種角色權限相對簡單、模糊,不利于擴展。 
          2、權限角色:一個角色擁有一個權限的集合。授權驗證時,需要判斷當前角色是否擁有該權限。這種角色權限可以對該角色進行詳細的權限描述,適合更復雜的權限設計。 
          下面將詳細描述對兩種角色模式的授權實現(xiàn)。 

          二、授權實現(xiàn) 

          Shiro支持三種方式實現(xiàn)授權過程: 
          • 編碼實現(xiàn)
          • 注解實現(xiàn)
          • JSP Taglig實現(xiàn)
          1、基于編碼的授權實現(xiàn) 

          1.1基于傳統(tǒng)角色授權實現(xiàn) 
          當需要驗證用戶是否擁有某個角色時,可以調用Subject 實例的hasRole*方法驗證。 
          Java代碼  收藏代碼
          1. Subject currentUser = SecurityUtils.getSubject();  
          2. if (currentUser.hasRole("administrator")) {  
          3.     //show the admin button  
          4. else {  
          5.     //don't show the button?  Grey it out?  
          6. }  

          相關驗證方法如下: 
          Subject方法描述
          hasRole(String roleName)當用戶擁有指定角色時,返回true
          hasRoles(List<String> roleNames)按照列表順序返回相應的一個boolean值數(shù)組
          hasAllRoles(Collection<String> roleNames)如果用戶擁有所有指定角色時,返回true

          斷言支持 
          Shiro還支持以斷言的方式進行授權驗證。斷言成功,不返回任何值,程序繼續(xù)執(zhí)行;斷言失敗時,將拋出異常信息。使用斷言,可以使我們的代碼更加簡潔。 
          Java代碼  收藏代碼
          1. Subject currentUser = SecurityUtils.getSubject();  
          2. //guarantee that the current user is a bank teller and  
          3. //therefore allowed to open the account:  
          4. currentUser.checkRole("bankTeller");  
          5. openBankAccount();  

          斷言的相關方法: 
          Subject方法描述
          checkRole(String roleName)斷言用戶是否擁有指定角色
          checkRoles(Collection<String> roleNames)斷言用戶是否擁有所有指定角色
          checkRoles(String... roleNames)對上一方法的方法重載

          1.2 基于權限角色授權實現(xiàn) 
          相比傳統(tǒng)角色模式,基于權限的角色模式耦合性要更低些,它不會因角色的改變而對源代碼進行修改,因此,基于權限的角色模式是更好的訪問控制方式。 
          它的代碼實現(xiàn)有以下幾種實現(xiàn)方式: 
          1、基于權限對象的實現(xiàn) 
          創(chuàng)建org.apache.shiro.authz.Permission的實例,將該實例對象作為參數(shù)傳遞給Subject.isPermitted()進行驗證。 
          Java代碼  收藏代碼
          1. Permission printPermission = new PrinterPermission("laserjet4400n", "print");  
          2. Subject currentUser = SecurityUtils.getSubject();  
          3. if (currentUser.isPermitted(printPermission)) {  
          4.     //show the Print button  
          5. else {  
          6.     //don't show the button?  Grey it out?  
          7. }  
          8. Permission printPermission = new PrinterPermission("laserjet4400n", "print");  
          9. Subject currentUser = SecurityUtils.getSubject();  
          10. if (currentUser.isPermitted(printPermission)) {  
          11.     //show the Print button  
          12. else {  
          13.     //don't show the button?  Grey it out?  
          14. }  

          相關方法如下: 
          Subject方法描述
          isPermitted(Permission p)Subject擁有制定權限時,返回treu
          isPermitted(List<Permission> perms)返回對應權限的boolean數(shù)組
          isPermittedAll(Collection<Permission> perms)Subject擁有所有制定權限時,返回true

          2、 基于字符串的實現(xiàn) 
          相比笨重的基于對象的實現(xiàn)方式,基于字符串的實現(xiàn)便顯得更加簡潔。 
          Java代碼  收藏代碼
          1. Subject currentUser = SecurityUtils.getSubject();  
          2. if (currentUser.isPermitted("printer:print:laserjet4400n")) {  
          3.     //show the Print button  
          4. else {  
          5.     //don't show the button?  Grey it out?  
          6. }  

          使用冒號分隔的權限表達式是org.apache.shiro.authz.permission.WildcardPermission 默認支持的實現(xiàn)方式。 
          這里分別代表了 資源類型:操作:資源ID 

          類似基于對象的實現(xiàn)相關方法,基于字符串的實現(xiàn)相關方法: 
          isPermitted(String perm)、isPermitted(String... perms)、isPermittedAll(String... perms) 

          基于權限對象的斷言實現(xiàn) 
          Java代碼  收藏代碼
          1. Subject currentUser = SecurityUtils.getSubject();  
          2. //guarantee that the current user is permitted  
          3. //to open a bank account:  
          4. Permission p = new AccountPermission("open");  
          5. currentUser.checkPermission(p);  
          6. openBankAccount();  

          基于字符串的斷言實現(xiàn) 
          Java代碼  收藏代碼
          1. Subject currentUser = SecurityUtils.getSubject();  
          2. //guarantee that the current user is permitted  
          3. //to open a bank account:  
          4. currentUser.checkPermission("account:open");  
          5. openBankAccount();  

          斷言實現(xiàn)的相關方法 
          Subject方法說明
          checkPermission(Permission p)斷言用戶是否擁有制定權限
          checkPermission(String perm)斷言用戶是否擁有制定權限
          checkPermissions(Collection<Permission> perms)斷言用戶是否擁有所有指定權限
          checkPermissions(String... perms)斷言用戶是否擁有所有指定權限

          2、基于注解的授權實現(xiàn) 
          Shiro注解支持AspectJ、Spring、Google-Guice等,可根據(jù)應用進行不同的配置。 

          相關的注解: 
          @ RequiresAuthentication 
          可以用戶類/屬性/方法,用于表明當前用戶需是經(jīng)過認證的用戶。 
          Java代碼  收藏代碼
          1. @RequiresAuthentication  
          2. public void updateAccount(Account userAccount) {  
          3.     //this method will only be invoked by a   
          4.     //Subject that is guaranteed authenticated  
          5.     ...  
          6. }  

          @ RequiresGuest 
          表明該用戶需為”guest”用戶 

          @ RequiresPermissions 
          當前用戶需擁有制定權限 
          Java代碼  收藏代碼
          1. @RequiresPermissions("account:create")  
          2. public void createAccount(Account account) {  
          3.     //this method will only be invoked by a Subject  
          4.     //that is permitted to create an account  
          5.     ...  
          6. }  

          @RequiresRoles 
          當前用戶需擁有制定角色 

          @ RequiresUser 
          當前用戶需為已認證用戶或已記住用戶 

          3、基于JSP  TAG的授權實現(xiàn) 
          Shiro提供了一套JSP標簽庫來實現(xiàn)頁面級的授權控制。 
          在使用Shiro標簽庫前,首先需要在JSP引入shiro標簽: 
          Java代碼  收藏代碼
          1. <%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>  

          下面一一介紹Shiro的標簽: 
          guest標簽 
          驗證當前用戶是否為“訪客”,即未認證(包含未記住)的用戶 
          Xml代碼  收藏代碼
          1. <shiro:guest>  
          2.     Hi there!  Please <a href="login.jsp">Login</a> or <a href="signup.jsp">Signup</a> today!  
          3. </shiro:guest>  

          user標簽 
          認證通過或已記住的用戶 
          Xml代碼  收藏代碼
          1. <shiro:user>  
          2.     Welcome back John!  Not John? Click <a href="login.jsp">here<a> to login.  
          3. </shiro:user>  

          authenticated標簽 
          已認證通過的用戶。不包含已記住的用戶,這是與user標簽的區(qū)別所在。 
          Xml代碼  收藏代碼
          1. <shiro:authenticated>  
          2.     <a href="updateAccount.jsp">Update your contact information</a>.  
          3. </shiro:authenticated>  

          notAuthenticated標簽 
          未認證通過用戶,與authenticated標簽相對應。與guest標簽的區(qū)別是,該標簽包含已記住用戶。 
          Xml代碼  收藏代碼
          1. <shiro:notAuthenticated>  
          2.     Please <a href="login.jsp">login</a> in order to update your credit card information.  
          3. </shiro:notAuthenticated>  

          principal 標簽 
          輸出當前用戶信息,通常為登錄帳號信息 
          Xml代碼  收藏代碼
          1. Hello, <shiro:principal/>, how are you today?  

          hasRole標簽 
          驗證當前用戶是否屬于該角色 
          Xml代碼  收藏代碼
          1. <shiro:hasRole name="administrator">  
          2.     <a href="admin.jsp">Administer the system</a>  
          3. </shiro:hasRole>  

          lacksRole標簽 
          與hasRole標簽邏輯相反,當用戶不屬于該角色時驗證通過 
          Xml代碼  收藏代碼
          1. <shiro:lacksRole name="administrator">  
          2.     Sorry, you are not allowed to administer the system.  
          3. </shiro:lacksRole>  

          hasAnyRole標簽 
          驗證當前用戶是否屬于以下任意一個角色。 
          Xml代碼  收藏代碼
          1. <shiro:hasAnyRoles name="developer, project manager, administrator">  
          2.     You are either a developer, project manager, or administrator.  
          3. </shiro:lacksRole>  

          hasPermission標簽 
          驗證當前用戶是否擁有制定權限 
          Xml代碼  收藏代碼
          1. <shiro:hasPermission name="user:create">  
          2.     <a href="createUser.jsp">Create a new User</a>  
          3. </shiro:hasPermission>  

          lacksPermission標簽 
          與hasPermission標簽邏輯相反,當前用戶沒有制定權限時,驗證通過 
          Xml代碼  收藏代碼
          1. <shiro:hasPermission name="user:create">  
          2.     <a href="createUser.jsp">Create a new User</a>  
          3. </shiro:hasPermission>  


          三、Shiro授權的內部處理機制 
           
          1、在應用程序中調用授權驗證方法(Subject的isPermitted*或hasRole*等) 
          2、Sbuject的實例通常是DelegatingSubject類(或子類)的實例對象,在認證開始時,會委托應用程序設置的securityManager實例調用相應的isPermitted*或hasRole*方法。 
          3、接下來SecurityManager會委托內置的Authorizer的實例(默認是ModularRealmAuthorizer 類的實例,類似認證實例,它同樣支持一個或多個Realm實例認證)調用相應的授權方法。 
          4、每一個Realm將檢查是否實現(xiàn)了相同的 Authorizer 接口。然后,將調用Reaml自己的相應的授權驗證方法。 

          當使用多個Realm時,不同于認證策略處理方式,授權處理過程中: 
          1、當調用Realm出現(xiàn)異常時,將立即拋出異常,結束授權驗證。 
          2、只要有一個Realm驗證成功,那么將認為授權成功,立即返回,結束認證。 

          轉自http://kdboy.iteye.com/blog/1155450

          posted on 2013-09-05 17:04 小秦 閱讀(359) 評論(0)  編輯  收藏


          只有注冊用戶登錄后才能發(fā)表評論。


          網(wǎng)站導航:
           
          主站蜘蛛池模板: 沂源县| 磐安县| 六盘水市| 晋宁县| 贵溪市| 凤阳县| 丰都县| 兴和县| 驻马店市| 通化县| 伊川县| 专栏| 保德县| 新宁县| 苏尼特右旗| 溧水县| 宜都市| 饶河县| 沁源县| 扎赉特旗| 东阳市| 万全县| 锡林浩特市| 大竹县| 上栗县| 绥滨县| 西吉县| 龙山县| 固阳县| 大姚县| 浙江省| 万山特区| 襄城县| 黔西| 黄山市| 通江县| 桑日县| 牙克石市| 津市市| 凤山市| 香河县|