版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
Spring源代碼解析(十):SpringAcegi框架授權(quán)的實(shí)現(xiàn)2009-08-11(周二)11:04SpringSpring被圍觀一共有280個(gè)打醬油的路過+我們從FilterSecuritylnterceptor我們從入手看看怎樣進(jìn)行授權(quán)的:如轉(zhuǎn)載請(qǐng)注明,轉(zhuǎn)載自: [ /r/本文鏈接:/2009/08/11/231-htmlJava代碼〃這里是攔截器攔截HTTP請(qǐng)求的入口publicvoiddoFilter(ServletRequestrequest,ServletResponseresponse,FilterChainchain)throwslOException,ServletException{Filterinvocationfi=newFilterlnvocation(request,response,chain);invoke(fi);}〃這是具體的攔截調(diào)用publicvoidinvoke(Filterlnvocationfi)throwsIOException,ServletException{if((fi.getRequest()!=null)&&(fi.getRequest().getAttribute(FILTER_APPLIED)!=nuII)&&observeOncePerRequest){〃在第一次進(jìn)行過安全檢查之后就不會(huì)再做了fi.getChain().doFilter(fi.getRequest(),fi.getResponse());}else{〃這是第一次收到相應(yīng)的請(qǐng)求,需要做安全檢測,同時(shí)把標(biāo)志為設(shè)置好-FILTER_APPLIED,下次就再有請(qǐng)求就不會(huì)作相同的安全檢查了if(fi.getRequest()!=null){fi.getRequest().setAttribute(FILTER_APPLIED,Boolean.TRUE);}〃這里是做安全檢查的地方InterceptorStatusTokentoken=super.beforelnvocation(fi);〃接著向攔截器鏈執(zhí)行try{fi.getChain().doFilter(fi.getRequest(),fi.getResponse());}finally{super.afterlnvocation(token,null);}}}Java代碼〃這里是攔截器攔截HTTP請(qǐng)求的入口publicvoiddoFilter(ServletRequestrequest,ServletResponseresponse,FilterChainchain)throwslOException,ServletException{FilterInvocationfi=newFilterInvocation(request,response,chain);invoke(fi);}〃這是具體的攔截調(diào)用publicvoidinvoke(FilterInvocationfi)throwsIOException,ServletException{if((fi.getRequest()!=null)&&(fi.getRequest().getAttribute(FILTER_APPLIED)!=nuII)&&observeOncePerRequest){〃在第一次進(jìn)行過安全檢查之后就不會(huì)再做了fi.getChain().doFilter(fi.getRequest(),fi.getResponse());}else{〃這是第一次收到相應(yīng)的請(qǐng)求,需要做安全檢測,同時(shí)把標(biāo)志為設(shè)置好-FILTER_APPLIED,下次就再有請(qǐng)求就不會(huì)作相同的安全檢查了if(fi.getRequest()!=null){fi.getRequest().setAttribute(FILTER_APPLIED,Boolean.TRUE);}〃這里是做安全檢查的地方InterceptorStatusTokentoken=super.beforeInvocation(fi);〃接著向攔截器鏈執(zhí)行try{fi.getChain().doFilter(fi.getRequest(),fi.getResponse());}finally{super.afterlnvocation(token,null);}}}我們看看在AbstractSecurityInterceptor是怎樣對(duì)HTTP請(qǐng)求作安全檢測的:Java代碼protectedlnterceptorStatusTokenbeforelnvocation(Objectobject){Assert.notNull(object,"Objectwasnull");3.if(!getSecureObjectClass().isAssignableFrom(object.getClass())){thrownewIllegalArgumentException("Securityinvocationattemptedforobject"+object.getClass().getName()+"butAbstractSecuritylnterceptoronlyconfiguredtosupportsecureobjectsoftype:"+getSecureObjectClass());}〃這里讀取配置FilterSecuritylnterceptor的ObjectDefinitionSource屬性,這些屬性配置了資源的安全設(shè)置ConfigAttributeDefinitionattr=this.obtainObjectDefinitionSource().getAttributes(object);12.if(attr==null){if(rejectPubliclnvocations){thrownewlllegalArgumentException("NopublicinvocationsareallowedviathisAbstractSecurityInterceptor."+"Thisindicatesaconfigurationerrorbecausethe"+"AbstractSecurityInterceptor.rejectPublicInvocationspropertyissetto'true'");}20.if(logger.isDebugEnabled()){logger.debug("Publicobject-authenticationnotattempted");}24.publishEvent(newPubliclnvocationEvent(object));26.returnnull;//nofurtherworkpost-invocation}29.30.if(logger.isDebugEnabled()){logger.debug("Secureobject:"+object.toString()+";ConfigAttributes:"+attr.toString());}〃這里從SecurityContextHolder中去取Authentication對(duì)象,一般在登錄時(shí)會(huì)放到SecurityContextHolder中去if(SecurityContextHolder.getContext().getAuthentication()==null){credentialsNotFound(messages.getMessage("AbstractSecuritylnterceptor.authenticationNotFound","AnAuthenticationobjectwasnotfoundintheSecurityContext"),object,attr);}39.//如果前面沒有處理鑒權(quán),這里需要對(duì)鑒權(quán)進(jìn)行處理Authenticationauthenticated;42.if(!SecurityContextHolder.getContext().getAuthentication().isAuthenticated()||alwaysReauthenticate){try{//調(diào)用配置好的AuthenticationManager處理鑒權(quán),如果鑒權(quán)不成功,拋出異常結(jié)束處理authenticated=this.authenticationManager.authenticate(SecurityContextHolder.getContext().getAuthentication());}catch(AuthenticationExceptionauthenticationException){throwauthenticationException;}50.//Wedon'tauthenticated.setAuthentication(true),becauseeachprovidershoulddothatif(logger.isDebugEnabled()){logger.debug("SuccessfullyAuthenticated:"+authenticated.toString());}〃這里把鑒權(quán)成功后得到的Authentication保存到SecurityContextHolder中供下次使用SecurityContextHolder.getContext().setAuthentication(authenticated);}else{//這里處理前面已經(jīng)通過鑒權(quán)的請(qǐng)求,先從SecurityContextHolder中去取得Authenticationauthenticated=SecurityContextHolder.getContext().getAuthentication();59.if(logger.isDebugEnabled()){logger.debug("PreviouslyAuthenticated:"+authenticated.toString());}}64.//這是處理授權(quán)的過程try{〃調(diào)用配置好的AccessDecisionManager來進(jìn)行授權(quán)this.accessDecisionManager.decide(authenticated,object,attr);}catch(AccessDeniedExceptionaccessDeniedException){〃授權(quán)不成功向外發(fā)布事件AuthorizationFailureEventevent=newAuthorizationFailureEvent(object,attr,authenticated,accessDeniedException);publishEvent(event);74.throwaccessDeniedException;}77.if(logger.isDebugEnabled()){logger.debug("Authorizationsuccessful");}AuthorizedEventevent=newAuthorizedEvent(object,attr,authenticated);publishEvent(event);84.//這里構(gòu)建一個(gè)RunAsManager來替代當(dāng)前的Authentication對(duì)象,默認(rèn)情況下使用的是NullRunAsManager會(huì)把SecurityContextHolder中的Authentication對(duì)象清空AuthenticationrunAs=this.runAsManager.buildRunAs(authenticated,object,attr);87.if(runAs==null){if(logger.isDebugEnabled()){logger.debug("RunAsManagerdidnotchangeAuthenticationobject");}92.//nofurtherworkpost-invocationreturnnewlnterceptorStatusToken(authenticated,false,attr,object);}else{if(logger.isDebugEnabled()){logger.debug("SwitchingtoRunAsAuthentication:"+runAs.toString());}99.SecurityContextHolder.getContext().setAuthentication(runAs);101.//reverttotoken.Authenticatedpost-invocationreturnnewlnterceptorStatusToken(authenticated, true,attr,object);}Java代碼Java代碼protectedInterceptorStatusTokenbeforelnvocation(Objectobject){Assert.notNull(object,"Objectwasnull");3.if(!getSecureObjectClass().isAssignableFrom(object.getClass())){thrownewlllegalArgumentException("Securityinvocationattemptedforobject"+object.getClass().getName()+"butAbstractSecurityInterceptoronlyconfiguredtosupportsecureobjectsoftype:"+getSecureObjectClass());}〃這里讀取配置FilterSecurityInterceptor的ObjectDefinitionSource屬性,這些屬性配置了資源的安全設(shè)置ConfigAttributeDefinitionattr=this.obtainObjectDefinitionSource().getAttributes(object);12.if(attr==null){if(rejectPublicInvocations){thrownewlllegalArgumentException("NopublicinvocationsareallowedviathisAbstractSecuritylnterceptor."+"Thisindicatesaconfigurationerrorbecausethe"+"AbstractSecuritylnterceptor.rejectPublicInvocationspropertyissetto'true'");}20.if(logger.isDebugEnabled()){logger.debug("Publicobject-authenticationnotattempted");}24.publishEvent(newPubliclnvocationEvent(object));26.returnnull;//nofurtherworkpost-invocation}29.30.if(logger.isDebugEnabled()){logger.debug("Secureobject:"+object.toString()+";ConfigAttributes:"+attr.toString());}〃這里從SecurityContextHolder中去取Authentication對(duì)象,一般在登錄時(shí)會(huì)放到SecurityContextHolder中去if(SecurityContextHolder.getContext().getAuthentication()==null){credentialsNotFound(messages.getMessage("AbstractSecuritylnterceptor.authenticationNotFound","AnAuthenticationobjectwasnotfoundintheSecurityContext"),object,attr);}39.//如果前面沒有處理鑒權(quán),這里需要對(duì)鑒權(quán)進(jìn)行處理Authenticationauthenticated;42.if(!SecurityContextHolder.getContext().getAuthentication().isAuthenticated()||alwaysReauthenticate){try{//調(diào)用配置好的AuthenticationManager處理鑒權(quán),如果鑒權(quán)不成功,拋出異常結(jié)束處理authenticated=this.authenticationManager.authenticate(SecurityContextHolder.getContext().getAuthentication());}catch(AuthenticationExceptionauthenticationException){throwauthenticationException;}50.//Wedon'tauthenticated.setAuthentication(true),becauseeachprovidershoulddothatif(logger.isDebugEnabled()){logger.debug("SuccessfullyAuthenticated:"+authenticated.toString());}〃這里把鑒權(quán)成功后得到的Authentication保存到SecurityContextHolder中供下次使用SecurityContextHolder.getContext().setAuthentication(authenticated);}else{//這里處理前面已經(jīng)通過鑒權(quán)的請(qǐng)求,先從SecurityContextHolder中去取得Authenticationauthenticated=SecurityContextHolder.getContext().getAuthentication();59.if(logger.isDebugEnabled()){logger.debug("PreviouslyAuthenticated:"+authenticated.toString());}}64.//這是處理授權(quán)的過程try{〃調(diào)用配置好的AccessDecisionManager來進(jìn)行授權(quán)this.accessDecisionManager.decide(authenticated,object,attr);}catch(AccessDeniedExceptionaccessDeniedException){〃授權(quán)不成功向外發(fā)布事件AuthorizationFailureEventevent=newAuthorizationFailureEvent(object,attr,authenticated,accessDeniedException);publishEvent(event);74.throwaccessDeniedException;}77.if(logger.isDebugEnabled()){logger.debug("Authorizationsuccessful");}81.AuthorizedEventevent=newAuthorizedEvent(object,attr,authenticated);publishEvent(event);84.//這里構(gòu)建一個(gè)RunAsManager來替代當(dāng)前的Authentication對(duì)象,默認(rèn)情況下使用的是NullRunAsManager會(huì)把SecurityContextHolder中的Authentication對(duì)象清空AuthenticationrunAs=this.runAsManager.buildRunAs(authenticated,object,attr);87.if(runAs==null){if(logger.isDebugEnabled()){logger.debug("RunAsManagerdidnotchangeAuthenticationobject");}92.//nofurtherworkpost-invocationreturnnewlnterceptorStatusToken(authenticated,false,attr,object);}else{if(logger.isDebugEnabled()){logger.debug("SwitchingtoRunAsAuthentication:"+runAs.toString());}99.SecurityContextHolder.getContext().setAuthentication(runAs);101.//reverttotoken.Authenticatedpost-invocationreturnnewlnterceptorStatusToken(authenticated, true, attr,object);}}到這里我們假設(shè)配置AffirmativeBased作為AccessDecisionManager:Java代碼〃這里定義了決策機(jī)制,需要全票才能通過publicvoiddecide(Authenticationauthentication,Objectobject,ConfigAttributeDefinitionconfig)throwsAccessDeniedException{〃這里取得配置好的迭代器集合Iteratoriter=this.getDecisionVoters().iterator();intdeny=0;〃依次使用各個(gè)投票器進(jìn)行投票,并對(duì)投票結(jié)果進(jìn)行計(jì)票while(iter.hasNext()){AccessDecisionVotervoter=(AccessDecisionVoter)iter.next();intresult=voter.vote(authentication,object,config);〃這是對(duì)投票結(jié)果進(jìn)行處理,如果遇到其中一票通過,那就授權(quán)通過,如果是棄權(quán)或者反對(duì),那就繼續(xù)投票switch(result){caseAccessDecisionVoter.ACCESS_GRANTED:return;15.caseAccessDecisionVoter.ACCESS_DENIED:〃這里對(duì)反對(duì)票進(jìn)行計(jì)數(shù)deny++;19.break;21.default:break;}}〃如果有反對(duì)票,拋出異常,整個(gè)授權(quán)不通過
if(deny>0){thrownewAccessDeniedException(messages.getMessage("AbstractAccessDecisionManager.accessDenied","Accessisdenied"));}31.//這里對(duì)棄權(quán)票進(jìn)行處理,看看是全是棄權(quán)票的決定情況,默認(rèn)是不通過,由allowlfAIIAbstainDecisions變量控制checkAllowlfAIIAbstainDecisions();}具體的投票由投票器進(jìn)行,我們這里配置了RoleVoter來進(jìn)行投票:publicintvote(Authenticationauthentication,Objectobject,ConfigAttributeDefinitionconfig){intresult=ACCESS_ABSTAIN;〃這里取得資源的安全配置Iteratoriter=config.getConfigAttributes();40.while(iter.hasNext()){ConfigAttributeattribute=(ConfigAttribute)iter.next();43.if(this.supports(attribute)){result=ACCESS_DENIED;46.//這里對(duì)資源配置的安全授權(quán)級(jí)別進(jìn)行判斷,也就是匹配ROLE為前綴的角色配置//遍歷每個(gè)配置屬性,如果其中一個(gè)匹配該主體持有的GrantedAuthority,則訪問被允許。for(inti=0;i<authentication.getAuthorities().length;i++){if(attribute.getAttribute().equals(authentication.getAuthorities()[i].getAuthority())){returnACCESS_GRANTED;TOC\o"1-5"\h\z}}}}56.returnresult;Java代碼}Java代碼〃這里定義了決策機(jī)制,需要全票才能通過publicvoiddecide(Authenticationauthentication,Objectobject,ConfigAttributeDefinitionconfig)throwsAccessDeniedException{〃這里取得配置好的迭代器集合Iteratoriter=this.getDecisionVoters().iterator();intdeny=0;〃依次使用各個(gè)投票器進(jìn)行投票,并對(duì)投票結(jié)果進(jìn)行計(jì)票while(iter.hasNext()){AccessDecisionVotervoter=(AccessDecisionVoter)iter.next();intresult=voter.vote(authentication,object,config);〃這是對(duì)投票結(jié)果進(jìn)行處理,如果遇到其中一票通過,那就授權(quán)通過,如果是棄權(quán)或者反對(duì),那就繼續(xù)投票switch(result){caseAccessDecisionVoter.ACCESS_GRANTED:return;15.caseAccessDecisionVoter.ACCESS_DENIED:〃這里對(duì)反對(duì)票進(jìn)行計(jì)數(shù)deny++;19.break;21.default:break;}}〃如果有反對(duì)票,拋出異常,整個(gè)授權(quán)不通過if(deny>0){thrownewAccessDeniedException(messages.getMessage("AbstractAccessDecisionManager.accessDenied","Accessisdenied"));}31.//這里對(duì)棄權(quán)票進(jìn)行處理,看看是全是棄權(quán)票的決定情況,默認(rèn)是不通過,由allowIfAIIAbstainDecisions變量控制checkAllowlfAIIAbstainDecisions();}具體的投票由投票器進(jìn)行,我們這里配置了RoleVoter來進(jìn)行投票:publicintvote(Authenticationauthentication,Objectobject,ConfigAttributeDefinitionconfig){intresult=ACCESS_ABSTAIN;〃這里取得資源的安全配置Iteratoriter=config.getConfigAttributes();40.while(iter.hasNext()){ConfigAttributeattribute=(ConfigAttribute)iter.next();43.if(this.supports(attribute)){result=ACCESS_DENIED;46.//這里對(duì)資源配置的安全授權(quán)級(jí)別進(jìn)行判斷,也就是匹配ROLE為前綴的角色配置//遍歷每個(gè)配置屬性,如果其中一個(gè)匹配該主體持有的GrantedAuthority,則訪問被允許。for(inti=0;i<authentication.getAuthorities().1ength;i++){if(attribute.getAttribute().equals(authentication.getAuthorities()[i].getAuthority())){return
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 科技發(fā)展與學(xué)科教育的互促關(guān)系研究
- 科技教育編程教育的普及與推廣
- DB4453T 30-2025廣藿香組培苗生產(chǎn)技術(shù)規(guī)程
- DB35T 2232-2024海峽兩岸共通 火龍果生產(chǎn)技術(shù)規(guī)程
- 東莞企業(yè)勞動(dòng)合同范本
- 個(gè)人貸款房屋抵押合同模板大全
- 業(yè)務(wù)經(jīng)營權(quán)轉(zhuǎn)讓合同
- 個(gè)人車位共有權(quán)買賣合同
- 臨時(shí)倉儲(chǔ)合同范本
- 兩人股權(quán)轉(zhuǎn)讓合同范本
- 2024-2030年全球及中國水楊酸行業(yè)市場現(xiàn)狀供需分析及市場深度研究發(fā)展前景及規(guī)劃可行性分析研究報(bào)告
- 體育館改造裝修工程施工組織設(shè)計(jì)
- 137案例黑色三分鐘生死一瞬間事故案例文字版
- 【魔鏡洞察】2024藥食同源保健品滋補(bǔ)品行業(yè)分析報(bào)告
- 2024-2030年中國潤滑油行業(yè)發(fā)展趨勢與投資戰(zhàn)略研究報(bào)告
- 鋼結(jié)構(gòu)工程施工(第五版) 課件 2項(xiàng)目四 高強(qiáng)度螺栓
- 機(jī)票預(yù)訂行業(yè)營銷策略方案
- 大學(xué)生就業(yè)指導(dǎo)(高等院校學(xué)生學(xué)習(xí)就業(yè)指導(dǎo)課程)全套教學(xué)課件
- 《實(shí)驗(yàn)診斷學(xué)》課件
- 眼的解剖結(jié)構(gòu)與生理功能課件
- 小學(xué)網(wǎng)管的工作總結(jié)
評(píng)論
0/150
提交評(píng)論