spring源代碼解析十一_第1頁
spring源代碼解析十一_第2頁
spring源代碼解析十一_第3頁
spring源代碼解析十一_第4頁
spring源代碼解析十一_第5頁
已閱讀5頁,還剩7頁未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(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ì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論