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