給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的處理迴圈。
----------------------------------------------------------