




版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領
文檔簡介
Spring源代碼解析(十):SpringAcegi框架授權的實現(xiàn)2009-08-11(周二)11:04SpringSpring被圍觀一共有280個打醬油的路過+我們從FilterSecuritylnterceptor我們從入手看看怎樣進行授權的:如轉(zhuǎn)載請注明,轉(zhuǎn)載自: [ /r/本文鏈接:/2009/08/11/231-htmlJava代碼〃這里是攔截器攔截HTTP請求的入口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){〃在第一次進行過安全檢查之后就不會再做了fi.getChain().doFilter(fi.getRequest(),fi.getResponse());}else{〃這是第一次收到相應的請求,需要做安全檢測,同時把標志為設置好-FILTER_APPLIED,下次就再有請求就不會作相同的安全檢查了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請求的入口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){〃在第一次進行過安全檢查之后就不會再做了fi.getChain().doFilter(fi.getRequest(),fi.getResponse());}else{〃這是第一次收到相應的請求,需要做安全檢測,同時把標志為設置好-FILTER_APPLIED,下次就再有請求就不會作相同的安全檢查了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是怎樣對HTTP請求作安全檢測的:Java代碼protectedlnterceptorStatusTokenbeforelnvocation(Objectobject){Assert.notNull(object,"Objectwasnull");3.if(!getSecureObjectClass().isAssignableFrom(object.getClass())){thrownewIllegalArgumentException("Securityinvocationattemptedforobject"+object.getClass().getName()+"butAbstractSecuritylnterceptoronlyconfiguredtosupportsecureobjectsoftype:"+getSecureObjectClass());}〃這里讀取配置FilterSecuritylnterceptor的ObjectDefinitionSource屬性,這些屬性配置了資源的安全設置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對象,一般在登錄時會放到SecurityContextHolder中去if(SecurityContextHolder.getContext().getAuthentication()==null){credentialsNotFound(messages.getMessage("AbstractSecuritylnterceptor.authenticationNotFound","AnAuthenticationobjectwasnotfoundintheSecurityContext"),object,attr);}39.//如果前面沒有處理鑒權,這里需要對鑒權進行處理Authenticationauthenticated;42.if(!SecurityContextHolder.getContext().getAuthentication().isAuthenticated()||alwaysReauthenticate){try{//調(diào)用配置好的AuthenticationManager處理鑒權,如果鑒權不成功,拋出異常結束處理authenticated=this.authenticationManager.authenticate(SecurityContextHolder.getContext().getAuthentication());}catch(AuthenticationExceptionauthenticationException){throwauthenticationException;}50.//Wedon'tauthenticated.setAuthentication(true),becauseeachprovidershoulddothatif(logger.isDebugEnabled()){logger.debug("SuccessfullyAuthenticated:"+authenticated.toString());}〃這里把鑒權成功后得到的Authentication保存到SecurityContextHolder中供下次使用SecurityContextHolder.getContext().setAuthentication(authenticated);}else{//這里處理前面已經(jīng)通過鑒權的請求,先從SecurityContextHolder中去取得Authenticationauthenticated=SecurityContextHolder.getContext().getAuthentication();59.if(logger.isDebugEnabled()){logger.debug("PreviouslyAuthenticated:"+authenticated.toString());}}64.//這是處理授權的過程try{〃調(diào)用配置好的AccessDecisionManager來進行授權this.accessDecisionManager.decide(authenticated,object,attr);}catch(AccessDeniedExceptionaccessDeniedException){〃授權不成功向外發(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.//這里構建一個RunAsManager來替代當前的Authentication對象,默認情況下使用的是NullRunAsManager會把SecurityContextHolder中的Authentication對象清空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屬性,這些屬性配置了資源的安全設置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對象,一般在登錄時會放到SecurityContextHolder中去if(SecurityContextHolder.getContext().getAuthentication()==null){credentialsNotFound(messages.getMessage("AbstractSecuritylnterceptor.authenticationNotFound","AnAuthenticationobjectwasnotfoundintheSecurityContext"),object,attr);}39.//如果前面沒有處理鑒權,這里需要對鑒權進行處理Authenticationauthenticated;42.if(!SecurityContextHolder.getContext().getAuthentication().isAuthenticated()||alwaysReauthenticate){try{//調(diào)用配置好的AuthenticationManager處理鑒權,如果鑒權不成功,拋出異常結束處理authenticated=this.authenticationManager.authenticate(SecurityContextHolder.getContext().getAuthentication());}catch(AuthenticationExceptionauthenticationException){throwauthenticationException;}50.//Wedon'tauthenticated.setAuthentication(true),becauseeachprovidershoulddothatif(logger.isDebugEnabled()){logger.debug("SuccessfullyAuthenticated:"+authenticated.toString());}〃這里把鑒權成功后得到的Authentication保存到SecurityContextHolder中供下次使用SecurityContextHolder.getContext().setAuthentication(authenticated);}else{//這里處理前面已經(jīng)通過鑒權的請求,先從SecurityContextHolder中去取得Authenticationauthenticated=SecurityContextHolder.getContext().getAuthentication();59.if(logger.isDebugEnabled()){logger.debug("PreviouslyAuthenticated:"+authenticated.toString());}}64.//這是處理授權的過程try{〃調(diào)用配置好的AccessDecisionManager來進行授權this.accessDecisionManager.decide(authenticated,object,attr);}catch(AccessDeniedExceptionaccessDeniedException){〃授權不成功向外發(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.//這里構建一個RunAsManager來替代當前的Authentication對象,默認情況下使用的是NullRunAsManager會把SecurityContextHolder中的Authentication對象清空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);}}到這里我們假設配置AffirmativeBased作為AccessDecisionManager:Java代碼〃這里定義了決策機制,需要全票才能通過publicvoiddecide(Authenticationauthentication,Objectobject,ConfigAttributeDefinitionconfig)throwsAccessDeniedException{〃這里取得配置好的迭代器集合Iteratoriter=this.getDecisionVoters().iterator();intdeny=0;〃依次使用各個投票器進行投票,并對投票結果進行計票while(iter.hasNext()){AccessDecisionVotervoter=(AccessDecisionVoter)iter.next();intresult=voter.vote(authentication,object,config);〃這是對投票結果進行處理,如果遇到其中一票通過,那就授權通過,如果是棄權或者反對,那就繼續(xù)投票switch(result){caseAccessDecisionVoter.ACCESS_GRANTED:return;15.caseAccessDecisionVoter.ACCESS_DENIED:〃這里對反對票進行計數(shù)deny++;19.break;21.default:break;}}〃如果有反對票,拋出異常,整個授權不通過
if(deny>0){thrownewAccessDeniedException(messages.getMessage("AbstractAccessDecisionManager.accessDenied","Accessisdenied"));}31.//這里對棄權票進行處理,看看是全是棄權票的決定情況,默認是不通過,由allowlfAIIAbstainDecisions變量控制checkAllowlfAIIAbstainDecisions();}具體的投票由投票器進行,我們這里配置了RoleVoter來進行投票: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.//這里對資源配置的安全授權級別進行判斷,也就是匹配ROLE為前綴的角色配置//遍歷每個配置屬性,如果其中一個匹配該主體持有的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代碼〃這里定義了決策機制,需要全票才能通過publicvoiddecide(Authenticationauthentication,Objectobject,ConfigAttributeDefinitionconfig)throwsAccessDeniedException{〃這里取得配置好的迭代器集合Iteratoriter=this.getDecisionVoters().iterator();intdeny=0;〃依次使用各個投票器進行投票,并對投票結果進行計票while(iter.hasNext()){AccessDecisionVotervoter=(AccessDecisionVoter)iter.next();intresult=voter.vote(authentication,object,config);〃這是對投票結果進行處理,如果遇到其中一票通過,那就授權通過,如果是棄權或者反對,那就繼續(xù)投票switch(result){caseAccessDecisionVoter.ACCESS_GRANTED:return;15.caseAccessDecisionVoter.ACCESS_DENIED:〃這里對反對票進行計數(shù)deny++;19.break;21.default:break;}}〃如果有反對票,拋出異常,整個授權不通過if(deny>0){thrownewAccessDeniedException(messages.getMessage("AbstractAccessDecisionManager.accessDenied","Accessisdenied"));}31.//這里對棄權票進行處理,看看是全是棄權票的決定情況,默認是不通過,由allowIfAIIAbstainDecisions變量控制checkAllowlfAIIAbstainDecisions();}具體的投票由投票器進行,我們這里配置了RoleVoter來進行投票: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.//這里對資源配置的安全授權級別進行判斷,也就是匹配ROLE為前綴的角色配置//遍歷每個配置屬性,如果其中一個匹配該主體持有的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等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年耐高溫濾料項目提案報告模板
- 2025年地區(qū)事業(yè)單位教師招聘考試數(shù)學學科專業(yè)知識試卷(數(shù)學分析)
- 2025年茶藝師(初級)職業(yè)技能鑒定理論考試試卷(茶葉市場分析)
- 歷史專業(yè)古代戰(zhàn)爭史研究練習題
- 2025年電子商務師(初級)職業(yè)技能鑒定試卷:電子商務數(shù)據(jù)分析報告撰寫
- 2025年消防工程師消防設施設備選型與消防安全設施布置試題
- 2025年聲樂演唱教師資質(zhì)認證模擬試題
- 2025年文化旅游演藝項目策劃運營:文化旅游演藝項目創(chuàng)新策劃與市場拓展研究報告
- 汽車行業(yè)供應鏈韌性優(yōu)化與風險管理創(chuàng)新路徑報告
- 深度挖掘2025年K2教育人工智能個性化學習系統(tǒng)應用效果與挑戰(zhàn)
- 2023年06月新疆生產(chǎn)建設兵團第一師阿拉爾市度“三支一扶”招募57名人員歷年高頻考點試題答案詳歷年高頻考點試題答案詳解
- 【拓展閱讀】徐孺子賞月
- 國家開放大學《農(nóng)村政策法規(guī)》形成性考核(平時作業(yè))參考答案
- 談判藥品審核備案表
- 2022微生物學考試題庫
- 介入治療臨床應用
- 寧夏中考歷史知識總結
- 日本與確保建筑物施工質(zhì)量相關的法律制度
- (完整版)焦慮自評量表(SAS)
- 生產(chǎn)安全事故考核辦法
- 中國歷史地理藍勇版課后題名詞解釋簡答論述題
評論
0/150
提交評論