Shiro受權(Authorization)

Authorization概述html

n概述java

  受權,又稱做爲訪問控制,是對資源的訪問管理的過程。換句話說,控制誰有權限在應用程序中作什麼。spring

  受權檢查的例子是:該用戶是否被容許訪問這個網頁,編輯此數據,查看此按鈕,或打印到這臺打印機?這些都是決定哪些是用戶可以訪問的。apache

n受權的三要素編程

  受權有着三個核心元素:權限、角色和用戶 。api

  咱們須要在應用程序中對用戶和權限創建關聯,一般的作法就是將權限分配給某個角色,而後將這個角色關聯一個或多個用戶。數組

n權限安全

  權限是Shiro安全機制最核心的元素。它在應用程序中明確聲明瞭被容許的行爲和表現。一個格式良好的權限聲明能夠清晰表達出用戶對該資源擁有的權限。session

n權限聲明和粒度app

  在shiro中主要經過前面學過的通配符表達式來完成。

 

n角色

  角色是一個命名的實體,一般表明一組行爲或職責。這些行爲演化爲你在一個軟件應用中能或者不能作的事情。角色一般是分配給用戶賬戶的,所以,經過分配,用戶可以「作」的事情能夠歸屬於各類角色。

nShiro支持的角色類型

1:隱式角色:一個角色表明着一系列的操做,當須要對某一操做進行受權驗證時,只需判斷是不是該角色便可。這種角色權限相對簡單、模糊,不利於擴展。

2:顯式角色:一個角色擁有一個權限的集合。受權驗證時,須要判斷當前角色是否擁有該權限。這種角色權限能夠對該角色進行詳細的權限描述,適合更復雜的權限設計。 Shiro官方推薦使用這種方式。

nShiro的三種受權方式

1:編寫代碼——在Java 代碼中用像if 和else 塊的結構執行受權檢查。

2:JDK 的註解——你能夠添加受權註解給你的Java 方法。

3:JSP/GSP 標籤庫——你能夠控制基於角色和權限的JSP 或者GSP 頁面輸出。

 

編程受權

n經過使用subject的方法來實現角色的判斷,常見的api:

hasRole(String roleName) :返回true 若是Subject 被分配了指定的角色
hasRoles(List<String> roleNames) :返回一個與方法參數中目錄一致的hasRole 結果的數組。
hasAllRoles(Collection<String> roleNames):返回true 若是Subject 被分配了全部的角色

n斷言支持

  Shiro還支持以斷言的方式進行受權驗證。斷言成功,不返回任何值,程序繼續執行;斷言失敗時,將拋出異常信息。方法大體以下:

checkRole(String roleName) 、checkRoles(Collection<String>roleNames)、checkRoles(String… roleNames)

n基於權限對象的實現

Permission printPermission = new PrinterPermission("laser400n", "print");

相關方法:

isPermitted(Permission p)、isPermitted(List<Permission> perms)、isPermittedAll(Collection<Permission> perms)

 n基於字符串的實現

if (currentUser.isPermitted("printer:print:laserjet4400n"))

相關方法:

isPermitted(String perm)、isPermitted(String... perms)、isPermittedAll(String... perms)

 n固然上述權限的實現也均可以採用斷言的方式

  相關方法:

checkPermission(Permission p)
checkPermission(String perm)
checkPermissions(Collection<Permission> perms)
checkPermissions(String... perms)

 基於註解的受權

n須要有AOP框架的支持,這裏選擇spring,先看看怎麼集成配置,看例子:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:context="http://www.springframework.org/schema/context"
  xmlns:aop="http://www.springframework.org/schema/aop"
  xmlns:tx="http://www.springframework.org/schema/tx"
  xsi:schemaLocation="
  http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
  http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
  http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
  http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
      <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
      <context:component-scan base-package="cn.javass"></context:component-scan>     
      <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
  depends-on="lifecycleBeanPostProcessor" >
  <property name="proxyTargetClass" value="true"/>
  </bean>
  <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
 
  <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
  <property name="securityManager" ref="securityManager" />
  </bean>
  <bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
  <property name="staticMethod" value="org.apache.shiro.SecurityUtils.setSecurityManager"/>
  <property name="arguments" ref="securityManager"/>
  </bean>
 
      <bean id="securityManager" class="org.apache.shiro.mgt.DefaultSecurityManager"> 
      <property name="cacheManager" ref="cacheManager"/> 
          <property name="realm" ref="myRealm"/> 
          <property name="sessionManager" ref="sessionManager"/>  
  </bean>
  <bean id="sessionManager" class="org.apache.shiro.session.mgt.DefaultSessionManager">
  </bean>
  <bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager" />
  <bean id="myRealm" class="org.apache.shiro.realm.text.IniRealm">
  <property name="resourcePath" value="D:/wp/src/TestShiro.ini"></property> 
  </bean>
</beans>

 

n測試用的HelloAnno

@Service
public class HelloAnno {
  @Autowired
  private org.apache.shiro.mgt.SecurityManager sm = null;
 
  @RequiresAuthentication
  @RequiresPermissions({"p1"})
  public void t(){
  System.out.println("ok=========");
  }
  public void login(){
  UsernamePasswordToken token = new UsernamePasswordToken("javass","cc"); 
  token.setRememberMe(true);
  SecurityUtils.setSecurityManager(sm);
 
  Subject currentUser = SecurityUtils.getSubject(); 
  currentUser.login(token);
  }
  public static void main(String[] args) {
   ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
   HelloAnno t = (HelloAnno)ctx.getBean("helloAnno"); 
   t.login();
   t.t();
  }
}

nShiro提供的註解

1:@RequiresAuthentication :要求當前Subject 已經在當前的session 中被驗證經過才能被註解的類/實例/方法訪問或調用。

2:@RequiresGuest :要求當前的Subject 是一個「guest」,也就是他們必須是在以前的session中沒有被驗證或記住才能被註解的類/實例/方法訪問或調用。

3:@RequiresPermissions:要求當前的Subject 被容許一個或多個權限,以便執行註解的方法,好比:@RequiresPermissions("account:create")

4:@RequiresRoles:要求當前的Subject 擁有全部指定的角色。若是他們沒有,則該方法將不會被執行,並且AuthorizationException 異常將會被拋出。好比:@RequiresRoles("administrator")

5:@RequiresUser:須要當前的Subject 是一個應用程序用戶才能被註解的類/實例/方法訪問或調用。要麼是經過驗證被確認,或者在以前session 中的'RememberMe'服務被記住。

受權的順序

 

nStep 1:應用程序或框架代碼調用任何Subject的hasRole*, checkRole*, isPermitted*,或者checkPermission*方法的變體,傳遞任何所需的權限或角色

nStep 2:Subject的實例,一般是DelegatingSubject(或子類)表明應用程序的SecurityManager 經過調用securityManager的幾乎各自相同的方法。

nStep 3:SecurityManager,實現org.apache.shiro.authz.Authorizer 接口,他定義了全部Subject 具體的受權方法 。默認狀況下,authorizer 實例是一個ModularRealmAuthorizer 實例,它支持協調任何受權操做過程當中的一個或多個Realm 實例。

nStep 4:每一個配置好的Realm 被檢查是否實現了相同的Authorizer接口。若是是,Realm 各自的hasRole*, checkRole*,isPermitted*,或checkPermission*方法將被調用。


理解ModularRealmAuthorizer

            nModularRealmAuthorizer 將遍歷其內部的Realm 集合,並按迭代順序與每個進行交互。每一個Realm 的交互功能以下:

1:若是Realm 本身實現了Authorizer 接口,它的各個Authorizer方法將被調用。

(1)若是Realm 的方法致使異常,該異常將會以AuthorizationException 的形式傳遞給調用者。這將短路受權過程,任何剩餘的Realm 將不會被訪問

(2)若是該Realm 的方法是一個返回布爾值的hasRole*或者isPermitted*的變體,而且該返回值爲true,真值將會當即被返回,同時任何剩餘的Realm 都將被短路,這種行爲能提升性能。

2:若是Realm 不實現Authorizer 接口,它會被忽略


瞭解全局的PermissionResolver

       n當執行基於字符串的權限檢查是,大多數Shiro 的默認Realm 實現首先將該字符串轉換成一個實際的Permission 實例,用的是內部默認實現的WildcardPermissionResolver。

       n若是你想要支持本身的權限字符串語法,並且你想要全部配置的Realm 實例支持該語法,你能夠將你的PermissionResolver 設置爲全局的。

        n若是你想配置一個全局的PermissionResolver,每一個用來接收配置的PermissionResolver 的Realm 必須實現PermissionResolverAware 接口。這樣保證了配置的實例可以被每一個支持該配置的Realm 轉發。

        n相似的,還有全局的RolePermissionResolver,但請注意:因爲這種轉換角色名到權限的概念很是特定於應用程序,Shiro 默認Realm 的實現並不使用它們


私塾在線 原創,轉載請註明 http://sishuok.com/forum/blogPost/list/0/7456.html

相關文章
相關標籤/搜索