1. 程式人生 > >給JFinal新增Shiro外掛功能,支援Shiro所有註解-使用篇

給JFinal新增Shiro外掛功能,支援Shiro所有註解-使用篇

基於JDK1.6打包好的包括原始碼的Shiro外掛在以下地址:

http://git.oschina.net/myaniu/jfinalshiroplugin/blob/master/dist/JFinalShiroPlugin-1.0.jar

Shiro共有5個註解,分別如下:

  • RequiresAuthentication:使用該註解標註的類,例項,方法在訪問或呼叫時,當前Subject必須在當前session中已經過認證。

  • RequiresGuest:使用該註解標註的類,例項,方法在訪問或呼叫時,當前Subject可以是“gust”身份,不需要經過認證或者在原先的session中存在記錄。

  • RequiresPermissions:當前Subject需要擁有某些特定的許可權時,才能執行被該註解標註的方法。如果當前Subject不具有這樣的許可權,則方法不會被執行。

  • RequiresRoles:當前Subject必須擁有所有指定的角色時,才能訪問被該註解標註的方法。如果當天Subject不同時擁有所有指定角色,則方法不會執行還會丟擲AuthorizationException異常。

  • RequiresUser:當前Subject必須是應用的使用者,才能訪問或呼叫被該註解標註的類,例項,方法。

多個註解的問題:

Shiro的認證註解處理是有內定的處理順序的,如果有個多個註解的話,前面的通過了會繼續檢查後面的,若不通過則直接返回,處理順序依次為(與實際宣告順序無關):
RequiresRoles
RequiresPermissions
RequiresAuthentication
RequiresUser
RequiresGuest
例如:你同時生命了RequiresRoles和RequiresPermissions,那就要求擁有此角色的同時還得擁有相應的許可權。

1)RequiresRoles

?
1 2 3 4 5 6 @Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface RequiresRoles { String[] value(); Logical logical() default Logical.AND;  }

可以用在Controller或者方法上。可以多個roles,預設邏輯為 AND也就是所有具備所有role才能訪問。

示例:

?
1 2 3 4 5 6 7 8 屬於user角色 @RequiresRoles("user") 必須同時屬於user和admin角色 @RequiresRoles({"user","admin"}) 屬於user或者admin之一。 @RequiresRoles(value={"user","admin"},logical=Logical.OR)

2)RequiresPermissions

?
1 2 3 4 5 6 @Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface RequiresPermissions { String[] value(); Logical logical() default Logical.AND;  }

RequiresRoles及其類似,使用如下

?
1 2 3 @RequiresPermissions("index:hello") @RequiresPermissions({"index:hello","index:world"}) @RequiresPermissions(value={"index:hello","index:world"},logical=Logical.OR)

3)RequiresAuthentication,RequiresUser,RequiresGuest

這三個使用方法類似。

?
1 2 3 @RequiresAuthentication @RequiresUser @RequiresGusst

4)這個是本人額外新增的一個註解@ClearShiro,用來清除某個方法上的所有訪問控制註解。

這個主要用於某個Controller的絕大部分方法都需要某個角色的許可權,但是個別方法例外的情況。

?
1 2 3 4 @RequiresRoles("user") public class LoginController extends Controller { @ClearShiro public void index(){

使用時需要做以下事項:

1)Shiro依賴於slf4j,commons-beanutils,commons-logging三個jar包。

2)public void configConstant(Constants me) { 方法中需加入401,403錯誤程式碼處理。

分別對應如下:

RequiresGuest,RequiresAuthentication,RequiresUser,未滿足時,丟擲未經授權的異常。
如果沒有進行身份驗證,返回HTTP401狀態碼

RequiresRoles,RequiresPermissions授權異常,如果沒有許可權訪問對應的資源,返回HTTP狀態碼403。

?
1 2 3 4 me.setErrorView(401"/au/login.html"); me.setErrorView(403"/au/login.html"); me.setError404View("/404.html"); me.setError500View("/500.html");

3)頂一個routes成員變數。

?
1 2 3 4 5 public class AppConfig extends JFinalConfig { /** * 供Shiro外掛使用。 */ Routes routes;

4)在configRoute方法中加入this.routes = me;

?
1 2 3 4 5 public void configRoute(Routes me) { this.routes = me; // TODO Auto-generated method stub me.add("/", IndexController.class); me.add("/au",AdminUserController.class);

5)public void configPlugin(Plugins me) {方法的最好加入

?
1 2 3 4 5 6 7 //載入Shiro外掛 //me.add(new ShiroPlugin(routes)); ShiroPlugin shiroPlugin = new ShiroPlugin(this.routes); shiroPlugin.setLoginUrl("/login.do"); shiroPlugin.setSuccessUrl("/index.do"); shiroPlugin.setUnauthorizedUrl("/login.do"); me.add(shiroPlugin);

6)配置一個攔截器,我這是配置了一個全域性攔截器,在某些系統中,可以只給後他需要驗證的部分新增攔截器,前臺部分可以不用該訪問控制攔截器。

?
1 2 3 4 public void configInterceptor(Interceptors me) { // TODO Auto-generated method stub me.add(new ShiroInterceptor()); }

7)根據需要實現一個Realm,繼承自AuthorizingRealm即可。

可參考:

8)配置shiro.ini檔案,該檔案需放在 /WEB-INF/shiro.ini這個位置。我的shiro.ini如下:

?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 [main] #realm myRealm = com.lh.openapi.manager.shiro.ShiroDbRealm securityManager.realm = $myRealm #cache shiroCacheManager = org.apache.shiro.cache.ehcache.EhCacheManager shiroCacheManager.cacheManagerConfigFile = classpath:ehcache-shiro.xml securityManager.cacheManager = $shiroCacheManager #session sessionDAO = org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO sessionManager = org.apache.shiro.web.session.mgt.DefaultWebSessionManager sessionDAO.activeSessionsCacheName = shiro-activeSessionCache sessionManager.sessionDAO = $sessionDAO securityManager.sessionManager = $sessionManager securityManager.sessionManager.globalSessionTimeout = 360000 #這裡的規則,web.xml中的配置的ShiroFilter會使用到。 [urls] /** = anon /card/** = user /school/** = user /rpc/rest/** = perms[rpc:invoke], authc /** = authc

9)配置web.xml在所有filter前面新增

?
1 2 3 4 5 6 7 8 9 10 11 <listener> <listener-class>org.apache.shiro.web.env.EnvironmentLoaderListener</listener-class> </listener> <filter> <filter-name>shiro</filter-name> <filter-class>org.apache.shiro.web.servlet.ShiroFilter</filter-class> </filter> <filter-mapping> <filter-name>shiro</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>

若shiro.ini中配置了

?
1 2 3 4 [urls] /** = anon /card/** = user /school/** = user

相關訪問控制規則,ShiroFilter會優先匹配這些規則,這個規則通過後,才會執行JFinal的Filer。才會進入JFinal的處理迴圈。

----------------------------------------------------------