學(xué)了段時(shí)間的Shiro,自己總結(jié)一下shiro。
博客參考這里:http://jinnianshilongnian.iteye.com/blog/2049092

Subject即主體,外部應(yīng)用與subject進(jìn)行交互,subject記錄了當(dāng)前操作用戶;
SecurityManager即安全管理器,對全部的subject進(jìn)行安全管理,它是shiro的核心,負(fù)責(zé)對所有的subject進(jìn)行安全管理;Realm即領(lǐng)域,相當(dāng)于datasource數(shù)據(jù)源,securityManager進(jìn)行安全認(rèn)證需要通過Realm獲取用戶權(quán)限數(shù)據(jù),比如:如果用戶身份數(shù)據(jù)在數(shù)據(jù)庫那么realm就需要從數(shù)據(jù)庫獲取用戶身份信息。 注意:不要把realm理解成只是從數(shù)據(jù)源取數(shù)據(jù),在realm中還有認(rèn)證授權(quán)校驗(yàn)的相關(guān)的代碼。同時(shí)Shiro不知道你的用戶/權(quán)限存儲在哪及以何種格式存儲;所以我們一般在應(yīng)用中都需要實(shí)現(xiàn)自己的Realm;Authenticator即認(rèn)證器,對用戶身份進(jìn)行認(rèn)證,Authenticator是一個(gè)接口,shiro默認(rèn)提供ModularRealmAuthenticator實(shí)現(xiàn)類,通過ModularRealmAuthenticator基本上可以滿足大多數(shù)需求,也可以自定義認(rèn)證器。ModularRealmAuthenticator提供了單realm認(rèn)證和多realm認(rèn)證;代碼如下: PRotected AuthenticationInfo doAuthenticate(AuthenticationToken authenticationToken) throws AuthenticationException { assertRealmsConfigured(); Collection<Realm> realms = getRealms(); if (realms.size() == 1) { return doSingleRealmAuthentication(realms.iterator().next(), authenticationToken);//調(diào)用單realm } else { return doMultiRealmAuthentication(realms, authenticationToken);//調(diào)用多realm } } protected AuthenticationInfo doSingleRealmAuthentication(Realm realm, AuthenticationToken token) { if (!realm.supports(token)) { String msg = "Realm [" + realm + "] does not support authentication token [" + token + "]. Please ensure that the appropriate Realm implementation is " + "configured correctly or that the realm accepts AuthenticationTokens of this type."; throw new UnsupportedTokenException(msg); } AuthenticationInfo info = realm.getAuthenticationInfo(token); if (info == null) { String msg = "Realm [" + realm + "] was unable to find account data for the " + "submitted AuthenticationToken [" + token + "]."; throw new UnknownAccountException(msg); } return info; } protected AuthenticationInfo doMultiRealmAuthentication(Collection<Realm> realms, AuthenticationToken token) { AuthenticationStrategy strategy = getAuthenticationStrategy(); AuthenticationInfo aggregate = strategy.beforeAllAttempts(realms, token); if (log.isTraceEnabled()) { log.trace("Iterating through {} realms for PAM authentication", realms.size()); } for (Realm realm : realms) { aggregate = strategy.beforeAttempt(realm, token, aggregate); if (realm.supports(token)) { log.trace("Attempting to authenticate token [{}] using realm [{}]", token, realm); AuthenticationInfo info = null; Throwable t = null; try { info = realm.getAuthenticationInfo(token); } catch (Throwable throwable) { t = throwable; if (log.isDebugEnabled()) { String msg = "Realm [" + realm + "] threw an exception during a multi-realm authentication attempt:"; log.debug(msg, t); } } aggregate = strategy.afterAttempt(realm, token, info, aggregate, t); } else { log.debug("Realm [{}] does not support token {}. Skipping realm.", realm, token); } } aggregate = strategy.afterAllAttempts(token, aggregate); return aggregate; }Authorizer即授權(quán)器,用戶通過認(rèn)證器認(rèn)證通過,在訪問功能時(shí)需要通過授權(quán)器判斷用戶是否有此功能的操作權(quán)限。實(shí)現(xiàn)類大體上分為ModularRealmAuthorizer和 AuthorizingRealm。單realm配置時(shí)推薦使用AuthorizingRealm,因?yàn)椋篈uthenticationInfodoGetAuthenticationInfo(AuthenticationToken token):表示獲取身份驗(yàn)證信息;AuthorizationInfodoGetAuthorizationInfo(PrincipalCollection principals):表示根據(jù)用戶身份獲取授權(quán)信息。sessionManager即會話管理,shiro框架定義了一套會話管理,它不依賴web容器的session,所以shiro可以使用在非web應(yīng)用上,也可以將分布式應(yīng)用的會話集中在一點(diǎn)管理,此特性可使它實(shí)現(xiàn)單點(diǎn)登錄。sessionDao即會話Dao,AbstractSessionDAO提供了SessionDAO的基礎(chǔ)實(shí)現(xiàn),如生成會話ID等;CachingSessionDAO提供了對開發(fā)者透明的會話緩存的功能,只需要設(shè)置相應(yīng)的CacheManager即可;MemorySessionDAO直接在內(nèi)存中進(jìn)行會話維護(hù);而EnterpriseCacheSessionDAO提供了緩存功能的會話維護(hù),默認(rèn)情況下使用MapCache實(shí)現(xiàn),內(nèi)部使用ConcurrentHashMap保存緩存的會話。簡單配置: <!-- sessionID生成器 --> <bean id="javaUuidSessionIdGenerator" class="org.apache.shiro.session.mgt.eis.JavaUuidSessionIdGenerator"></bean> <!-- sessionDAO繼承EnterpriseCacheSessionDAO --> <bean id="sessionDao" class="lee.shiro.session.MySessionDao"> <property name="sessionIdGenerator" ref="javaUuidSessionIdGenerator"></property> <property name="activeSessionsCacheName" value="shiro-activeSessionCache"></property> </bean> <!-- 會話管理器 --> <bean id="sessionManager" class="org.apache.shiro.session.mgt.DefaultSessionManager"> <property name="sessionDAO" ref="sessionDao"></property> <property name="deleteInvalidSessions" value="true"></property> <property name="sessionValidationSchedulerEnabled" value="true"></property> <property name="globalSessionTimeout" value="1800000"></property> </bean>public class MySessionDAO extends CachingSessionDAO { private JdbcTemplate jdbcTemplate = JdbcTemplateUtils.jdbcTemplate(); protected Serializable doCreate(Session session) { Serializable sessionId = generateSessionId(session); assignSessionId(session, sessionId); String sql = "insert into sessions(id, session) values(?,?)"; jdbcTemplate.update(sql, sessionId, SerializableUtils.serialize(session)); return session.getId(); } protected void doUpdate(Session session) { if(session instanceof ValidatingSession && !((ValidatingSession)session).isValid()) { return; //如果會話過期/停止 沒必要再更新了 } String sql = "update sessions set session=? where id=?"; jdbcTemplate.update(sql, SerializableUtils.serialize(session), session.getId()); } protected void doDelete(Session session) { String sql = "delete from sessions where id=?"; jdbcTemplate.update(sql, session.getId()); } protected Session doReadSession(Serializable sessionId) { String sql = "select session from sessions where id=?"; List<String> sessionStrList = jdbcTemplate.queryForList(sql, String.class, sessionId); if(sessionStrList.size() == 0) return null; return SerializableUtils.deserialize(sessionStrList.get(0)); } } CacheManager:緩存控制器,來管理如用戶、角色、權(quán)限等的緩存的;因?yàn)檫@些數(shù)據(jù)基本上很少去改變,放到緩存中后可以提高訪問的性能;Cryptography:密碼模塊,Shiro提高了一些常見的加密組件用于如密碼加密/解密的;
新聞熱點(diǎn)
疑難解答