r即可。如果非常簡(jiǎn)單的cookie,可以直接實(shí)現(xiàn)RememberMeManager的幾個(gè)接口方法也行
【Apache Shiro in Spring】自定義filterChainDefinitions和Realm
文章出處
在Spring Context中定義shiroFilter(org.apache.shiro.spring.web.ShiroFilterFactoryBean)時(shí)需要為其filterChainDefinitions property賦值,這個(gè)屬性是個(gè)chainName-to-chainDefinition map of chain definitions,用于為URL定義過濾策略。
filterChainDefinitions是一個(gè)set method,他調(diào)用setFilterChainDefinitionMap(section),F(xiàn)ilterChainDefinitionMap是個(gè)Field。
比如,這是我定義的:
/404.htm = anon /main!main.html = anon /**.html = perms[myPerm_1]
在這里引用一下某前輩總結(jié)的chainDefinition,如下:
rest:比如/admins/user/**=rest[user],根據(jù)請(qǐng)求的方法,相當(dāng)于/admins/user/**=perms[user:method] ,其中method為post,get,delete等。
port:比如/admins/user/**=port[8081],當(dāng)請(qǐng)求的url的端口不是8081是跳轉(zhuǎn)到schemal://serverName:8081?queryString,其中schmal是協(xié)議http或https等,serverName是你訪問的host,8081是url配置里port的端口,queryString是你訪問的url里的?后面的參數(shù)。
perms:比如/admins/user/**=perms[user:add:*],perms參數(shù)可以寫多個(gè),多個(gè)時(shí)必須加上引號(hào),并且參數(shù)之間用逗號(hào)分割,比如/admins/user/**=perms["user:add:*,user:modify:*"],當(dāng)有多個(gè)參數(shù)時(shí)必須每個(gè)參數(shù)都通過才通過,想當(dāng)于isPermitedAll()方法。
roles:比如/admins/user/**=roles[admin],參數(shù)可以寫多個(gè),多個(gè)時(shí)必須加上引號(hào),并且參數(shù)之間用逗號(hào)分割,當(dāng)有多個(gè)參數(shù)時(shí),比如/admins/user/**=roles["admin,guest"],每個(gè)參數(shù)通過才算通過,相當(dāng)于hasAllRoles()方法。
anon:比如/admins/**=anon 沒有參數(shù),表示可以匿名使用。
authc:比如/admins/user/**=authc表示需要認(rèn)證才能使用,沒有參數(shù)
authcBasic:比如/admins/user/**=authcBasic沒有參數(shù)表示httpBasic認(rèn)證
ssl:比如/admins/user/**=ssl沒有參數(shù),表示安全的url請(qǐng)求,協(xié)議為https
user:比如/admins/user/**=user沒有參數(shù)表示必須存在用戶,當(dāng)?shù)侨氩僮鲿r(shí)不做檢查
一般情況下,我們可以將模塊作為一個(gè)授權(quán)單位,例如:
/blog!**.html = user
偶爾也會(huì)有將每一個(gè)URL作為一個(gè)授權(quán)單位進(jìn)行控制,例如:
/blog!doAddNewArticle.html = authc,perms[addArticle]
但是URL的數(shù)量讓人頭疼,也許可以每開發(fā)一個(gè)功能的時(shí)候打開XML文件寫入U(xiǎn)RL然后同步到SVN,或者我們也可以找一個(gè)人專門做這些事情,無論是添加、刪除功能還是修改方法名都通知這個(gè)人去做...換位思考一下,我不希望我是這個(gè)人...
所以我要把這些URL放在數(shù)據(jù)庫(kù)進(jìn)行管理。我要把他們統(tǒng)統(tǒng)Query出來放到filterChainDefinitions里。
我需要裝配一個(gè)Bean,實(shí)際上他是一個(gè)org.springframework.beans.factory.FactoryBean<Section>的實(shí)現(xiàn)。
<bean id="chainFilterBuff" class="king.common.ChainFilterBuff">
<property name="filterChainDefinitions">
/404.htm = anon
/main!main.html = anon
</property>
</bean>
然后將其注入:
<bean id="shiroFilter1" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager" />
<property name="loginUrl" value="/main!main.html" />
<property name="successUrl" value="/main!main.html" />
<property name="unauthorizedUrl" value="/unAuthorized.htm" />
<property name="filterChainDefinitionMap" ref="chainFilterBuff" />
</bean>
Java代碼中implements FactoryBean<Ini.Section>并實(shí)現(xiàn)需要Override的method,關(guān)鍵是getObject這個(gè)method:
private String filterChainDefinitions;
@Override
public Section getObject() throws Exception {
Ini ini = new Ini();
ini.load(filterChainDefinitions); //先載入XML中定義好的chain
Ini.Section section = ini.getSection(Ini.DEFAULT_SECTION_NAME);
/*
* 省略讀取步驟
* 繼續(xù)加入數(shù)據(jù)庫(kù)中的chain
* section.put("/**", "authc, roles[admin]");
*/
return section;
}
等等,這些僅僅是定義了權(quán)限。
我們需要在用戶訪問這些URL的時(shí)候去驗(yàn)證一下用戶是否具備當(dāng)前URL權(quán)限。
所以我定義了(事實(shí)上我們必須定義一個(gè)Realm,ShiroFilterFactoryBean需要SecurityManager,而我們使用的SecurityManager的實(shí)現(xiàn)類DefaultWebSecurityManager則需要一個(gè)Realm!):
<bean id="shiroDataBaseRealm" class="king.security.KingMainRealm">
并且Override了接口定義的method:
public class KingMainRealm extends AuthorizingRealm {
@Override
protected AuthorizationInfo doGetAuthorizationInfo( //授權(quán)
PrincipalCollection principals) {
UserBean _user = (UserBean) principals.fromRealm(getName()).iterator().next();
SimpleAuthorizationInfo authInfo = new SimpleAuthorizationInfo();
/*
* 省略
*/
return authInfo;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo( //認(rèn)證
AuthenticationToken token) throws AuthenticationException {
UserBean user = new UserBean();
UsernamePasswordToken userToken = (UsernamePasswordToken)token;
user.setUserName(userToken.getUsername());
user.setPassword(userToken.getPassword());
return new SimpleAuthenticationInfo(user, user.getPassword(), getName());
}
}
若已定義了需要請(qǐng)求的URL,用戶登錄時(shí)doGetAuthorizationInfo會(huì)被調(diào)用,剩下的就是為每一個(gè)用戶管理這些權(quán)限了。
也許我們可以創(chuàng)建角色關(guān)聯(lián)多個(gè)權(quán)限,用戶關(guān)聯(lián)多個(gè)角色,類似這樣的設(shè)置不同的層次。
按你喜歡的方式去做吧