下載本文檔
版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
Shiro使用簡介核心組件SubjectSecurityManagerRealms核心組件Subject:即“當前操作用戶”SecurityManager:它是Shiro框架的核心,典型的Facade模式,Shiro通過SecurityManager來管理內(nèi)部組件實例,并通過它來提供安全管理的各種服務(wù)Realm充當了Shiro與應(yīng)用安全數(shù)據(jù)間的“橋梁”或者“連接器”。也就是說,當對用戶執(zhí)行認證(登錄)和授權(quán)(訪問控制)驗證時,Shiro會從應(yīng)用配置的Realm中查找用戶及其權(quán)限信息Shiro完整架構(gòu)圖
其他主要組件Authenticator:認證,核實用戶身份Authorizer:授權(quán),訪問控制SessionManager:CacheManager:對Shiro的其他組件提供緩存支持Shiro認證過程
Shiro認證過程1、應(yīng)用程序構(gòu)建了一個終端用戶認證信息的AuthenticationToken實例后,調(diào)用Subject.login方法。
2、Sbuject的實例通常是DelegatingSubject類(或子類)的實例對象,在認證開始時,會委托應(yīng)用程序設(shè)置的securityManager實例調(diào)用securityManager.login(token)方法。
3、SecurityManager接受到token(令牌)信息后會委托內(nèi)置的Authenticator的實例(通常都是ModularRealmAuthenticator類的實例)調(diào)用authenticator.authenticate(token).ModularRealmAuthenticator在認證過程中會對設(shè)置的一個或多個Realm實例進行適配,它實際上為Shiro提供了一個可拔插的認證機制。
Shiro認證過程4、如果在應(yīng)用程序中配置了多個Realm,ModularRealmAuthenticator會根據(jù)配置的AuthenticationStrategy(認證策略)來進行多Realm的認證過程。在Realm被調(diào)用后,AuthenticationStrategy將對每一個Realm的結(jié)果作出響應(yīng)。
注:如果應(yīng)用程序中僅配置了一個Realm,Realm將被直接調(diào)用而無需再配置認證策略。
5、判斷每一個Realm是否支持提交的token,如果支持,Realm將調(diào)用getAuthenticationInfo(token);getAuthenticationInfo方法就是實際認證處理,我們通過覆蓋Realm的doGetAuthenticationInfo方法來編寫我們自定義的認證處理。認證代碼Subjectmyadmin=SecurityUtils.getSubject();if(!myadmin.isAuthenticated()){ UsernamePasswordTokentoken=new UsernamePasswordToken(account,password); token.setRememberMe(true);try{ myadmin.login(token);}catch(UnknownAccountExceptionuae){ message="用戶名不正確";return
ERROR;}認證代碼catch(IncorrectCredentialsExceptionice){ message="密碼錯誤"; return
ERROR;}catch(LockedAccountExceptionlae){ message="用戶被鎖"; return
ERROR;}catch(ExcessiveAttemptsExceptioneae){ message="用戶名或密碼錯誤"; return
ERROR;}catch(AuthenticationExceptionae){ message="用戶名或密碼錯誤"; return
ERROR;}}currentUser.logout();//退出代碼Shiro授權(quán)授權(quán)有著三個核心元素:權(quán)限、角色和用戶。權(quán)限Shiro權(quán)限聲明通常是使用以冒號分隔的表達式。下面以實例來說明權(quán)限表達式。
可查詢用戶數(shù)據(jù)
User:view
可查詢或編輯用戶數(shù)據(jù)
User:view,edit
可對用戶數(shù)據(jù)進行所有操作
User:*或User
可編輯id為123的用戶數(shù)據(jù)
User:edit:123
角色
Shiro支持兩種角色模式:
1、傳統(tǒng)角色:一個角色代表著一系列的操作,當需要對某一操作進行授權(quán)驗證時,只需判斷是否是該角色即可。這種角色權(quán)限相對簡單、模糊,不利于擴展。
2、權(quán)限角色:一個角色擁有一個權(quán)限的集合。授權(quán)驗證時,需要判斷當前角色是否擁有該權(quán)限。這種角色權(quán)限可以對該角色進行詳細的權(quán)限描述,適合更復(fù)雜的權(quán)限設(shè)計。
授權(quán)實現(xiàn)Shiro支持三種方式實現(xiàn)授權(quán)過程:1編碼實現(xiàn)2注解實現(xiàn)3JSPTaglig實現(xiàn)Shiro授權(quán)的內(nèi)部處理機制
授權(quán)流程1、在應(yīng)用程序中調(diào)用授權(quán)驗證方法(Subject的isPermitted*或hasRole*等)
2、Sbuject的實例通常是DelegatingSubject類(或子類)的實例對象,在認證開始時,會委托應(yīng)用程序設(shè)置的securityManager實例調(diào)用相應(yīng)的isPermitted*或hasRole*方法。
3、接下來SecurityManager會委托內(nèi)置的Authorizer的實例(默認是ModularRealmAuthorizer類的實例,類似認證實例,它同樣支持一個或多個Realm實例認證)調(diào)用相應(yīng)的授權(quán)方法。
4、每一個Realm將檢查是否實現(xiàn)了相同的Authorizer接口。然后,將調(diào)用Reaml自己的相應(yīng)的授權(quán)驗證方法。
。
授權(quán)流程當使用多個Realm時,不同于認證策略處理方式,授權(quán)處理過程中:
1、當調(diào)用Realm出現(xiàn)異常時,將立即拋出異常,結(jié)束授權(quán)驗證。
2、只要有一個Realm驗證成功,那么將認為授權(quán)成功,立即返回,結(jié)束認證Shiro有3中認證策略的具體實現(xiàn):
AtLeastOneSuccessfulStrategy只要有一個(或更多)的Realm驗證成功,那么認證將被視為成功FirstSuccessfulStrategy第一個Realm驗證成功,整體認證將被視為成功,且后續(xù)Realm將被忽略AllSuccessfulStrategy所有Realm成功,認證才視為成功基于傳統(tǒng)角色授權(quán)實現(xiàn)
SubjectcurrentUser=SecurityUtils.getSubject();if(currentUser.hasRole("administrator")){}else{}相關(guān)驗證方法1.hasRole(StringroleName)當用戶擁有指定角色時,返回true2.hasRoles(List<String>roleNames)按照列表順序返回相應(yīng)的一個boolean值數(shù)組3.hasAllRoles(Collection<String>roleNames)如果用戶擁有所有指定角色時,返回true斷言支持
Shiro還支持以斷言的方式進行授權(quán)驗證。斷言成功,不返回任何值,程序繼續(xù)執(zhí)行;斷言失敗時,將拋出異常信息。使用斷言,可以使我們的代碼更加簡潔。SubjectcurrentUser=SecurityUtils.getSubject();currentUser.checkRole("bankTeller");openBankAccount();斷言的相關(guān)方法Subject方法描述checkRole(StringroleName)斷言用戶是否擁有指定角色checkRoles(Collection<String>roleNames)斷言用戶是否擁有所有指定角色checkRoles(String...roleNames)對上一方法的方法重載基于權(quán)限角色授權(quán)實現(xiàn)
相比傳統(tǒng)角色模式,基于權(quán)限的角色模式耦合性要更低些,它不會因角色的改變而對源代碼進行修改,因此,基于權(quán)限的角色模式是更好的訪問控制方式。
它的代碼實現(xiàn)有以下幾種實現(xiàn)方式:基于權(quán)限對象的實現(xiàn)PermissionprintPermission=newPrinterPermission("laserjet4400n","print");SubjectcurrentUser=SecurityUtils.getSubject();if(currentUser.isPermitted(printPermission)){//showthePrintbutton}else{//don'tshowthebutton?Greyitout?}PermissionprintPermission=newPrinterPermission("laserjet4400n","print");SubjectcurrentUser=SecurityUtils.getSubject();if(currentUser.isPermitted(printPermission)){//showthePrintbutton}else{//don'tshowthebutton?Greyitout?}相關(guān)方法1.isPermitted(Permissionp)Subject擁有制定權(quán)限時,返回treu2.isPermitted(List<Permission>perms)返回對應(yīng)權(quán)限的boolean數(shù)組3.isPermittedAll(Collection<Permission>perms)Subject擁有所有制定權(quán)限時,返回true基于字符串的實現(xiàn)
SubjectcurrentUser=SecurityUtils.getSubject();if(currentUser.isPermitted("printer:print:laserjet4400n")){//showthePrintbutton}else{//don'tshowthebutton?Greyitout?}斷言實現(xiàn)
SubjectcurrentUser=SecurityUtils.getSubject();Permissionp=newAccountPermission("open");currentUser.checkPermission(p);openBankAccount();SubjectcurrentUser=SecurityUtils.getSubject();currentUser.checkPermission("account:open");openBankAccount();斷言實現(xiàn)的相關(guān)方法1.checkPermission(Permissionp)斷言用戶是否擁有制定權(quán)限2.checkPermission(Stringperm)斷言用戶是否擁有制定權(quán)限3.checkPermissions(Collection<Permission>perms)斷言用戶是否擁有所有指定權(quán)限4.checkPermissions(String...perms)斷言用戶是否擁有所有指定權(quán)限基于注解的授權(quán)實現(xiàn)
@RequiresAuthentication
@RequiresGuest@RequiresPermissions("account:create")@RequiresRoles
@RequiresUser
基于JSPTAG的授權(quán)實現(xiàn)
<%@taglibprefix="shiro"uri=""%><shiro:guest></shiro:guest><shiro:authenticated></shiro:authenticated><shiro:notAuthenticated></shiro:notAuthenticated>Hello,<shiro:principal/>,howareyoutoday?<shiro:hasRolename="administrator"></shiro:hasRole><shiro:lacksRolename="administrator"></shiro:lacksRole><shiro:hasAnyRolesname="developer,projectmanager,administrator">.</shiro:lacksRole><shiro:hasPermissionname="user:create"></shiro:hasPermission><shiro:lacksPermissionname="user:create"></shiro:lacksPermission>Realm實現(xiàn)在認證、授權(quán)內(nèi)部實現(xiàn)機制中都有提到,最終處理都將交給Real進行處理。因為在Shiro中,最終是通過Realm來獲取應(yīng)用程序中的用戶、角色及權(quán)限信息的。通常情況下,在Realm中會直接從我們的數(shù)據(jù)源中獲取Shiro需要的驗證信息。可以說,Realm是專用于安全框架的DAO.
認證實現(xiàn)
Shiro的認證過程最終會交由Realm執(zhí)行,這時會調(diào)用Realm的getAuthenticationInfo(token)方法。
該方法主要執(zhí)行以下操作:
1、檢查提交的進行認證的令牌信息
2、根據(jù)令牌信息從數(shù)據(jù)源(通常為數(shù)據(jù)庫)中獲取用戶信息
3、對用戶信息進行匹配驗證。
4、驗證通過將返回一個封裝了用戶信息的AuthenticationInfo實例。
5、驗證失敗則拋出AuthenticationException異常信息。
Realm代碼@OverrideprotectedAuthenticationInfodoGetAuthenticationInfo(AuthenticationTokenauthcToken)throwsAuthenticationException{UsernamePasswordTokentoken=(UsernamePasswordToken)authcToken;Adminuser=(Admin)adminDao.query().is("account",token.getUsername()).result();
if(user!=null){
return
newSimpleAuthenticationInfo(user.getAccount(),user.getPassword(),getName());}else{
return
null;}}授權(quán)實現(xiàn)
而授權(quán)實現(xiàn)則與認證實現(xiàn)非常相似,在我們自定義的Realm中,重載doGetAuthorizationInfo()方法,重寫獲取用戶權(quán)限的方法即可。Realm代碼@OverrideprotectedAuthorizationInfodoGetAuthorizationInfo(PrincipalCollectionprincipals){Stringname=getName();Iteratoriterator=principals.fromRealm(name).iterator();StringuserName=null;if(iterator.hasNext()){userName=(String)iterator.next();}Adminuser=(Admin)adminDao.findOne("account",userName);if(user.getRoleSet()!=null){BuguMapper.fetchCascade(user,"roleSet");}
if(user!=null&&user.getRoleSet()!=null){SimpleAuthorizationInfoinfo=newSimpleAuthorizationInfo();
for(Rolegroup:user.getRoleSet()){
info.addRole(group.getName());
if(group.getPerssionSet()!=null){BuguMapper.fetchCascade(group,"perssionSet");
Iteratorit=group.getPerssionSet().iterator();
while(it.hasNext()){info.addStringPermission(((Permission)it.next()).getName());}}
}
returninfo;}else{
return
null;}Shiro配置ApacheShiro的配置主要分為四部分:
對象和屬性的定義與配置URL的過濾器配置靜態(tài)用戶配置靜態(tài)角色配置其中,由于用戶、角色一般由后臺進行操作的動態(tài)數(shù)據(jù),因此Shiro配置一般僅包含前兩項的配置。
ApacheShiro的大多數(shù)組件是基于POJO的,因此我們可以使用POJO兼容的任何配置機制進行配置,例如:Java代碼、SpingXML、YAML、JSON、ini文件等等。基于spring的配置<beanid="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"><propertyname="realm"ref="myRealm"/><propertyname="sessionMode"value="native"/><propertyname="sessionManager"ref="sessionManager"/></bean><beanid="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager"><propertyname="sessionDAO"ref="sessionDAO"/></bean><beanid="sessionDAO" class="org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO"></bean><beanid="myRealm"class="mons.utils.MongodbRealm"> <propertyname="adminDao"ref="adminDao"></property></bean><beanid="rolesAny"class="mons.context.RolesAnyAuthorizationFilter"></bean>基于spring的配置<beanid="shiroFilter"class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"><propertyname="securityManager"ref="securityManager"/><propertyname="loginUrl"value="/login/admin_login.jsp"/><propertyname="successUrl"value="/admins/"/><propertyname="unauthorizedUrl"value="/shows/error/no_permission.jsp"/><propertyname="filters"><util:map><entrykey="rolesAny"value-ref="rolesAny"/></util:map></property><propertyname="filterChainDefinitions"><value>/admins/news/indexRebuild**=authc,rolesAny["系統(tǒng)常規(guī)管理,超級管理員"]/admins/product/indexRebuild**=authc,rolesAny["系統(tǒng)常規(guī)管理,超級管理員"]/admins/member/indexRebuild**=authc,rolesAny["系統(tǒng)常規(guī)管理,超級管理員"]</value></property>
</bean>基于ini文件的配置[main]shiro.loginUrl=/login/admin_login.jspauthc.successUrl=/admins/roles.unauthorizedUrl=/shows/error/no_permission.jspperms.unauthorizedUrl=/shows/error/no_permission.jspinirealm=org.apache.shiro.realm.text.IniRealminirealm.resourcePath=classpath:shiro.inimons.utils.MongodbRealmadminDao=cn.eyes.core.admin.AdminDaomyrealm.adminDao=$adminDaosecurityManager.realms=$inirealm,$myrealmsessionManager=org.apache.shiro.web.session.mgt.DefaultWebSessionManagersecurityManager.sessionManager=$sessionManagermons.context.RolesAnyAuthorizationFiltersecurityManager.sessionManager.sessionListeners=$rolesAny[users]admin=1234567,*基于ini文件的配置[roles]admin=*[urls]/admins/news/indexRebuild**=authc,perms[indexrebuild:*]/admins/news/**.jsp=authc,roles[資訊管理],roles[超級管理員]/admins/news/**=authc,roles[資訊管理],roles[超級管理員]/admins/survey/**=authc,rolesAny["資訊管理,超級管理員"]/admins/survey/**.jsp=authc,roles[資訊管理],roles[超級管理員]/admins/**=authcURL過濾器配置說明URL_Ant_Path_Expression=Path_Specific_Filter_Chain[urls]
/index.html=anon
/user/create=anon
/user/**=authc
/admin/**=authc,roles[administrator]
/rest/**=authc,rest
/remoting/rpc/**=authc,perms["remote:invoke"]
URL表達式說明
1、URL目錄是基于HttpServletRequest.getContextPath()此目錄設(shè)置
2、URL可使用通配符,**代表任意子目錄
3、Shiro驗證URL時,URL匹配成功便不再繼續(xù)匹配查找。所以要注意配置文件中的URL順序,尤其在使用通配符時。
FilterChain定義說明
1、一個URL可以配置多個Filter,使用逗號分隔
2、當設(shè)置多個過濾器時,全部驗證通過,才視為通過
3、部分過濾器可指定參數(shù),如perms,roles
Shiro內(nèi)置的FilterChain
anonorg.apache.shiro.web.filter.authc.AnonymousFilterauthcorg.apache.shiro.web.filter.authc.FormAuthenticationFilterauthcBasicorg.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilterpermsorg.apache.shiro.web.filter.authz.PermissionsAuthorizationFilterportorg.apache.shiro.web.filter.authz.PortFilterrestorg.apache.shiro.web.filter.authz.HttpMethodPermissionFilterrolesorg.apache.shiro.web.filter.authz.RolesAuthorizationFiltersslorg.apache.shiro.web.filter.authz.SslFilteruserorg.apache.shiro.web.filter.authc.UserFilter內(nèi)置過濾器詳解rest:例如/admins/user/**=authc,rest[user]根據(jù)請求的方法,想當與/admins/user/**=authc,perms[user:method]port:例如/admins/user/**=authc,prot[8081]當請求的rul端口不是8081時,跳轉(zhuǎn)到
perms:例如/admins/user/**=authc,perms[“user:add:*”]內(nèi)置過濾器詳解prems參數(shù)可以寫多個,當寫多個時要加上雙引號,并且參數(shù)之間用逗號分割roles例如/admins/user/**=authc,roles[admin]參數(shù)可以寫多個,當寫多個時要加上雙引號,并且參數(shù)之間用逗號分割anon例如/admins/**=anon沒有參數(shù),表示可以匿名使用內(nèi)置過濾器詳解authc:例如/admins/user/**=authc
表示需要認證才能使用,沒有參數(shù)authcBasic:例如/admins/user/**=authcBasic沒有參數(shù),表示httpBasic認證,沒有參數(shù)ssl:例如/admins/user/**=ssl沒有參數(shù),表示安全url請求,httpsuser:例如/admins/user/**=user沒有參數(shù),表示存在用戶,當?shù)侨氩僮鲿r不做檢查會話管理可在任何應(yīng)用或架構(gòu)層一致地使用SessionAPI.那些希望使用會話的應(yīng)用開發(fā)者,不必被迫使用Servlet或EJB容器了?;蛘?,如果正在使用這些容器,開發(fā)者現(xiàn)在也可以選擇使用在任何層統(tǒng)一一致的會話API,取代Servlet或EJB機制。
代碼Sessionsession=subject.getSession();Sessionsession=subject.getSession(booleancreate);session.setAttribute("key",someValue);session.getAttribute(“key”)Datetimestamp=session.getLastAccessTime();session.setTimeout(millis);
加密<beanid="md5Matcher"class="org.apache.shiro.authc.credential.Md5CredentialsMatcher"></bean>
<beanid="myRealm"cl
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 幼兒園重量測量課程設(shè)計
- 9686樂高課程設(shè)計
- 幼兒園擺放椅子課程設(shè)計
- 中班玩具繪畫課程設(shè)計
- java簡易qq設(shè)計課程設(shè)計
- 四層公寓施工課程設(shè)計
- 幕墻安裝增補合同范例
- 房屋租賃合同購買合同范例
- 水果搬運售賣合同范例
- 造橋技術(shù)轉(zhuǎn)讓合同范例
- 商品(服裝類)基礎(chǔ)知識
- 機電安裝工程質(zhì)量通病及防治措施
- 行政管理學(xué)的判斷題
- 傳感器原理與應(yīng)用課程設(shè)計報告磁電式輪速傳感器系統(tǒng)設(shè)計
- 濟南市建設(shè)工程竣工測量技術(shù)規(guī)程
- 語音放大電路的設(shè)計畢業(yè)論文
- 滑動模板施工工法
- 合同履行確認單(模板).doc
- 框架結(jié)構(gòu)內(nèi)力計算-豎向彎矩二次分配,水平D值法講解
- 《初中團隊一體化工作模式的實踐與研究》
- 工程增項簽證單樣本
評論
0/150
提交評論