寫在前面
什么事Shiro?
Shiro是一個(gè)強(qiáng)大易用的Java安全框架,用在身份驗(yàn)證、授權(quán)、密碼學(xué)和會(huì)話管理。有了Shiro易于理解的API,我們可以快速、輕松地獲得任何應(yīng)用程序,從小的移動(dòng)應(yīng)用程序到大的網(wǎng)絡(luò)甚至企業(yè)應(yīng)用程序都是可以的。
Shiro的主要框架圖:
走進(jìn)shiro
Subject是主體,外部應(yīng)用與subject進(jìn)行交互,subject則會(huì)記錄當(dāng)前操作用戶,將用戶的概念理解為當(dāng)前操作的主體,可以是一個(gè)通過瀏覽器請(qǐng)求的用戶,也可以是一個(gè)運(yùn)行的程序。 Subject在shiro中是一個(gè)接口,接口中定義了很多認(rèn)證授相關(guān)的方法,外部程序通過subject進(jìn)行認(rèn)證授權(quán),而subject是通過SecurityManager安全管理器進(jìn)行認(rèn)證授權(quán)的。
SecurityManager
SecurityManager是安全管理器,對(duì)全部的subject進(jìn)行安全管理,它是shiro的核心,負(fù)責(zé)對(duì)所有的subject進(jìn)行安全管理。通過SecurityManager可以完成subject的認(rèn)證、授權(quán)等,實(shí)質(zhì)上SecurityManager是通過Authenticator進(jìn)行認(rèn)證,通過Authorizer進(jìn)行授權(quán),通過sessionManager進(jìn)行會(huì)話管理等。
SecurityManager是一個(gè)接口,同時(shí)它自身也繼承了Authenticator, Authorizer, SessionManager這三個(gè)接口。
Authorizer
Authorizer是授權(quán)器,用戶通過認(rèn)證器認(rèn)證通過,在訪問功能時(shí)需要通過授權(quán)器判斷用戶是否有此功能的操作權(quán)限。
Authenticator
Authenticator是認(rèn)證器,可以對(duì)用戶身份進(jìn)行認(rèn)證,Authenticator是一個(gè)接口,shiro提供ModularRealmAuthenticator實(shí)現(xiàn)類,通過ModularRealmAuthenticator基本上可以滿足大多數(shù)需求,也可以自定義認(rèn)證器。
realm
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)的代碼。
SessionDAO
SessionDAO是會(huì)話dao層,是對(duì)session會(huì)話操作的一套接口,比如要將session存儲(chǔ)到數(shù)據(jù)庫,可以通過jdbc將會(huì)話存儲(chǔ)到數(shù)據(jù)庫。
sessionManager
sessionManager是會(huì)話管理,shiro框架定義了一套會(huì)話管理,它不依賴web容器的session,所以shiro可以使用在非web應(yīng)用上,也可以將分布式應(yīng)用的會(huì)話集中在一點(diǎn)管理,此特性可使它成為單點(diǎn)登錄的利器。
Cryptography
Cryptography是密碼管理,shiro提供了一套加密/解密的組件,方便開發(fā)。比如提供常用的散列、加/解密等功能。
CacheManager
CacheManager是緩存管理,將用戶權(quán)限數(shù)據(jù)存儲(chǔ)在緩存,這樣可以提高性能。
shiro認(rèn)證與授權(quán)的具體實(shí)現(xiàn)
第一步:添加jar包
<!– shiro –> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-core</artifactId> <version>1.4.0</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.4.0</version> </dependency>
第二步:配置web.xml
<filter> <filter-name>shiroFilter</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> <!– 設(shè)置true由servlet容器控制filter的生命周期 –> <init-param> <param-name>targetFilterLifecycle</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>shiroFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
第三步:自定義Realm 繼承AuthorizingRealm 重寫 AuthorizationInfo(授權(quán)) 和 AuthenticationInfo(認(rèn)證)
簡(jiǎn)單的測(cè)試 根據(jù)個(gè)人的設(shè)置和需求改變的?,F(xiàn)在數(shù)據(jù)是死的,運(yùn)用的時(shí)候需要從數(shù)據(jù)庫中得到
/** * @author IT講壇 * @date 2018/12/26 14:05 */public class CustomRealm extends AuthorizingRealm { /** * 授權(quán) * @param principalCollection * @return */ @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { String userName = (String) principalCollection.getPrimaryPrincipal(); List<String> permissionList=new ArrayList<String>(); permissionList.add(\”user:add\”); permissionList.add(\”user:delete\”); if (userName.equals(\”zhou\”)) { permissionList.add(\”user:query\”); } SimpleAuthorizationInfo info=new SimpleAuthorizationInfo(); info.addStringPermissions(permissionList); info.addRole(\”admin\”); return info; } /** * 認(rèn)證 * @param authenticationToken * @return * @throws AuthenticationException */ @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { String userName = (String) authenticationToken.getPrincipal(); if (\”\”.equals(userName)) { return null; } SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(userName,\”123456\”,this.getName()); return info; }}
第四步:配置spring-shiro.xml
<?xml version=\”1.0\” encoding=\”UTF-8\”?><beans xmlns=\”http://www.springframework.org/schema/beans\” xmlns:xsi=\”http://www.w3.org/2001/XMLSchema-instance\” xsi:schemaLocation=\”http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd\”> <!–開啟shiro的注解–> <bean id=\”advisorAutoProxyCreator\” class=\”org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator\”> <property name=\”proxyTargetClass\” value=\”true\”></property> </bean> <bean class=\”org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor\”/> <!–注入自定義的Realm–> <bean id=\”customRealm\” class=\”com.test.realm.CustomRealm\”></bean> <bean id=\”securityManager\” class=\”org.apache.shiro.web.mgt.DefaultWebSecurityManager\”> <property name=\”realm\” ref=\”customRealm\”></property> </bean> <!–配置ShiroFilter–> <bean id=\”shiroFilter\” class=\”org.apache.shiro.spring.web.ShiroFilterFactoryBean\”> <property name=\”securityManager\” ref=\”securityManager\”></property> <!–登入頁面–> <property name=\”loginUrl\” value=\”/login.jsp\”></property> <!–登入成功頁面–> <property name=\”successUrl\” value=\”/index.jsp\”/> <property name=\”filters\”> <map> <!–退出過濾器–> <entry key=\”logout\” value-ref=\”logoutFilter\” /> </map> </property> <!–URL的攔截–> <property name=\”filterChainDefinitions\” > <value> /share = authc /logout = logout </value> </property> </bean> <!–自定義退出LogoutFilter–> <bean id=\”logoutFilter\” class=\”com.test.filter.SystemLogoutFilter\”> <property name=\”redirectUrl\” value=\”/login\”/> </bean></beans>
說明:
securityManager: 這個(gè)屬性是必須的。
loginUrl: 沒有登錄的用戶請(qǐng)求需要登錄的頁面時(shí)自動(dòng)跳轉(zhuǎn)到登錄頁面,不是必須的屬性,不輸入地址的話會(huì)自動(dòng)尋找項(xiàng)目web項(xiàng)目的根目錄下的”/login.jsp”頁面。
successUrl: 登錄成功默認(rèn)跳轉(zhuǎn)頁面,不配置則跳轉(zhuǎn)至”/”。如果登陸前點(diǎn)擊的一個(gè)需要登錄的頁面,則在登錄自動(dòng)跳轉(zhuǎn)到那個(gè)需要登錄的頁面。不跳轉(zhuǎn)到此。
unauthorizedUrl: 沒有權(quán)限默認(rèn)跳轉(zhuǎn)的頁面。
Shiro中默認(rèn)的過濾器:
在spring中直接引入<import resource=\”spring-shiro.xml\”></import>
第五步:在spring-mvc.xml中配置權(quán)限的控制 異常的跳轉(zhuǎn)
<bean class=\”org.springframework.web.servlet.handler.SimpleMappingExceptionResolver\”> <property name=\”exceptionMappings\”> <props> <!–表示捕獲的異常 –> <prop key=\”org.apache.shiro.authz.UnauthorizedException\”> <!–捕獲該異常時(shí)跳轉(zhuǎn)的路徑 –> /403 </prop> <!–表示捕獲的異常 –> <prop key=\”org.apache.shiro.authz.UnauthenticatedException\”> <!–捕獲該異常時(shí)跳轉(zhuǎn)的路徑 –> /403 </prop> </props> </property> </bean>
寫在文末
最后給小伙伴們舉幾個(gè)配置實(shí)例
/admin=authc,roles[admin] 表示用戶必需已通過認(rèn)證,并擁有admin角色才可以正常發(fā)起’/admin’請(qǐng)求
/edit=authc,perms[admin:edit] 表示用戶必需已通過認(rèn)證,并擁有admin:edit權(quán)限才可以正常發(fā)起’/edit’請(qǐng)求
/home=user 表示用戶不一定需要已經(jīng)通過認(rèn)證,只需要曾經(jīng)被Shiro記住過登錄狀態(tài)就可以正常發(fā)起’/home’請(qǐng)求
歡迎大家多多關(guān)注,評(píng)論留言區(qū)多多互動(dòng),交流學(xué)習(xí)心得。
版權(quán)聲明:本文內(nèi)容由互聯(lián)網(wǎng)用戶自發(fā)貢獻(xiàn),該文觀點(diǎn)僅代表作者本人。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如發(fā)現(xiàn)本站有涉嫌抄襲侵權(quán)/違法違規(guī)的內(nèi)容, 請(qǐng)發(fā)送郵件至 舉報(bào),一經(jīng)查實(shí),本站將立刻刪除。