日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

Spring Security源碼解析之權(quán)限訪(fǎng)問(wèn)控制是如何做到的

瀏覽:144日期:2023-07-14 17:58:54
目錄?、前文回顧一、再聊過(guò)濾器鏈二、過(guò)濾器的創(chuàng)建FilterSecurityInterceptor的創(chuàng)建ExceptionTranslationFilter的創(chuàng)建三、源碼流程FilterSecurityInterceptorExceptionTranslationFilter四、總結(jié)?、前文回顧

在實(shí)戰(zhàn)篇《話(huà)說(shuō)Spring Security權(quán)限管理(源碼詳解)》我們學(xué)習(xí)了Spring Security強(qiáng)大的訪(fǎng)問(wèn)控制能力,只需要進(jìn)行寥寥幾行的配置就能做到權(quán)限的控制,本篇來(lái)看看它到底是如何做到的。

一、再聊過(guò)濾器鏈

源碼篇中反復(fù)提到,請(qǐng)求進(jìn)來(lái)需要經(jīng)過(guò)的是一堆過(guò)濾器形成的過(guò)濾器鏈,走完過(guò)濾器鏈未拋出異常則可以繼續(xù)訪(fǎng)問(wèn)后臺(tái)接口資源,而最后一個(gè)過(guò)濾器就是來(lái)判斷請(qǐng)求是否有權(quán)限繼續(xù)訪(fǎng)問(wèn)后臺(tái)資源,如果沒(méi)有則會(huì)將拒絕訪(fǎng)問(wèn)的異常往上向異常過(guò)濾器拋,異常過(guò)濾器會(huì)對(duì)異常進(jìn)行翻譯,然后響應(yīng)給客戶(hù)端。

所以,一般情況下最后一個(gè)過(guò)濾器是做權(quán)限訪(fǎng)問(wèn)控制的核心過(guò)濾器FilterSecurityInterceptor ,而倒數(shù)第二個(gè)是異常翻譯過(guò)濾器ExceptionTranslationFilter ,將異常進(jìn)行翻譯然后響應(yīng)給客戶(hù)端。比如我們實(shí)戰(zhàn)項(xiàng)目過(guò)濾器鏈圖解

Spring Security源碼解析之權(quán)限訪(fǎng)問(wèn)控制是如何做到的

二、過(guò)濾器的創(chuàng)建FilterSecurityInterceptor的創(chuàng)建

這個(gè)過(guò)濾器的配置器是 ExpressionUrlAuthorizationConfigurer ,它的父類(lèi) AbstractInterceptUrlConfigurer 中的 configure() 方法創(chuàng)建了這個(gè)過(guò)濾器。

abstract class AbstractInterceptUrlConfigurer<C extends AbstractInterceptUrlConfigurer<C, H>, H extends HttpSecurityBuilder<H>>extends AbstractHttpConfigurer<C, H> {...@Overridepublic void configure(H http) throws Exception {FilterInvocationSecurityMetadataSource metadataSource = createMetadataSource(http);if (metadataSource == null) {return;}FilterSecurityInterceptor securityInterceptor = createFilterSecurityInterceptor(http, metadataSource, http.getSharedObject(AuthenticationManager.class));if (filterSecurityInterceptorOncePerRequest != null) {securityInterceptor.setObserveOncePerRequest(filterSecurityInterceptorOncePerRequest);}securityInterceptor = postProcess(securityInterceptor);http.addFilter(securityInterceptor);http.setSharedObject(FilterSecurityInterceptor.class, securityInterceptor);}...}

這個(gè)過(guò)濾器的配置器是在 HttpSecurity 的 authorizeRequests() 方法中apply進(jìn)來(lái)的,在我們自己配置的核心配置器中使用的就是該種基于 HttpServletRequest 限制訪(fǎng)問(wèn)的方式。

Spring Security源碼解析之權(quán)限訪(fǎng)問(wèn)控制是如何做到的

ExceptionTranslationFilter的創(chuàng)建

這個(gè)過(guò)濾器的配置器是 ExceptionHandlingConfigurer ,它自己的 configure() 方法中創(chuàng)建了這個(gè)過(guò)濾器。

public final class ExceptionHandlingConfigurer<H extends HttpSecurityBuilder<H>> extendsAbstractHttpConfigurer<ExceptionHandlingConfigurer<H>, H> {...@Overridepublic void configure(H http) throws Exception {AuthenticationEntryPoint entryPoint = getAuthenticationEntryPoint(http);ExceptionTranslationFilter exceptionTranslationFilter = new ExceptionTranslationFilter(entryPoint, getRequestCache(http));if (accessDeniedHandler != null) {exceptionTranslationFilter.setAccessDeniedHandler(accessDeniedHandler);}exceptionTranslationFilter = postProcess(exceptionTranslationFilter);http.addFilter(exceptionTranslationFilter);}...}

這個(gè)過(guò)濾器的配置器是在 HttpSecurity 的 exceptionHandling() 方法中apply進(jìn)來(lái)的,和上面不同的是,這個(gè)過(guò)濾器配置器會(huì)默認(rèn)被apply進(jìn) HttpSecurity,在 WebSecurityConfigurerAdapter 中的 init() 方法,里面調(diào)用了 getHttp() 方法,這里定義了很多默認(rèn)的過(guò)濾器配置,其中就包括當(dāng)前過(guò)濾器配置。

Spring Security源碼解析之權(quán)限訪(fǎng)問(wèn)控制是如何做到的

三、源碼流程FilterSecurityInterceptor 進(jìn)入:doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 進(jìn)入:invoke(FilterInvocation fi) 進(jìn)入:beforeInvocation(Object object)

這個(gè)方法里面有個(gè) attributes ,里面獲取的就是當(dāng)前request請(qǐng)求所能匹配中的權(quán)限Spel表達(dá)式,比如這里是 hasRole(’ROLE_BUYER’)Spring Security源碼解析之權(quán)限訪(fǎng)問(wèn)控制是如何做到的 方法源碼如下,繼續(xù)往下走

protected InterceptorStatusToken beforeInvocation(Object object) {...// 獲取當(dāng)前request請(qǐng)求所能匹配中的權(quán)限Spel表達(dá)式Collection<ConfigAttribute> attributes = this.obtainSecurityMetadataSource().getAttributes(object);...// Attempt authorizationtry {this.accessDecisionManager.decide(authenticated, object, attributes);}catch (AccessDeniedException accessDeniedException) {publishEvent(new AuthorizationFailureEvent(object, attributes, authenticated,accessDeniedException));throw accessDeniedException;}...}

進(jìn)入:decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes)

這里有個(gè)投票器,投票結(jié)果為1表示可以訪(fǎng)問(wèn)直接返回,投票結(jié)果為-1表示拒絕訪(fǎng)問(wèn),向上拋拒絕訪(fǎng)問(wèn)異常,這里使用的投票器是 WebExpressionVoter

public void decide(Authentication authentication, Object object,Collection<ConfigAttribute> configAttributes) throws AccessDeniedException {int deny = 0;for (AccessDecisionVoter voter : getDecisionVoters()) {int result = voter.vote(authentication, object, configAttributes);if (logger.isDebugEnabled()) {logger.debug('Voter: ' + voter + ', returned: ' + result);}switch (result) {case AccessDecisionVoter.ACCESS_GRANTED:return;case AccessDecisionVoter.ACCESS_DENIED:deny++;break;default:break;}}if (deny > 0) {throw new AccessDeniedException(messages.getMessage('AbstractAccessDecisionManager.accessDenied', 'Access is denied'));}// To get this far, every AccessDecisionVoter abstainedcheckAllowIfAllAbstainDecisions();}

進(jìn)入:vote(Authentication authentication, FilterInvocation fi, Collection<ConfigAttribute> attributes)

這里面其實(shí)就是使用Spring的Spel表達(dá)式進(jìn)行投票,使用請(qǐng)求中的權(quán)限表達(dá)式組裝Expression,使用Token令牌中的權(quán)限組裝EvaluationContext,然后調(diào)用 ExpressionUtils.evaluateAsBoolean(weca.getAuthorizeExpression(), ctx),

public int vote(Authentication authentication, FilterInvocation fi,Collection<ConfigAttribute> attributes) {assert authentication != null;assert fi != null;assert attributes != null;WebExpressionConfigAttribute weca = findConfigAttribute(attributes);if (weca == null) {return ACCESS_ABSTAIN;}EvaluationContext ctx = expressionHandler.createEvaluationContext(authentication,fi);ctx = weca.postProcess(ctx, fi);return ExpressionUtils.evaluateAsBoolean(weca.getAuthorizeExpression(), ctx) ? ACCESS_GRANTED: ACCESS_DENIED;}

evaluateAsBoolean() 方法里面就是調(diào)用Expression的 getValue() 方法,獲取實(shí)際的匹配結(jié)果,如下圖Spel表達(dá)式為 hasRole(’ROLE_BUYER’)Spring Security源碼解析之權(quán)限訪(fǎng)問(wèn)控制是如何做到的所以它實(shí)際調(diào)用的是 SecurityExpressionRoot#hasRole 方法(關(guān)于權(quán)限表達(dá)式對(duì)應(yīng)實(shí)際調(diào)用的方法,在《手把手教你如何使用Spring Security(下):訪(fǎng)問(wèn)控制》文章中已貼出,下面文章也補(bǔ)充一份),里面的邏輯其實(shí)就是判斷Token令牌中是否包含有 ROLE_BUYER 的角色,有的話(huà)返回true,否則返回false,如下為 SecurityExpressionRoot#hasRole 方法源碼:

private boolean hasAnyAuthorityName(String prefix, String... roles) {Set<String> roleSet = getAuthoritySet();for (String role : roles) {String defaultedRole = getRoleWithDefaultPrefix(prefix, role);if (roleSet.contains(defaultedRole)) {return true;}}return false;} 如果投票成功,則會(huì)一直返回到 invoke() 方法,再執(zhí)行后續(xù)過(guò)濾器,未拋異常表示該請(qǐng)求已經(jīng)有訪(fǎng)問(wèn)權(quán)限了 假如投票失敗,在 decide() 方法中會(huì)向上拋拒絕訪(fǎng)問(wèn)異常,一直往上拋直到被處理,往上反向跟蹤發(fā)現(xiàn)這個(gè)過(guò)濾器一直沒(méi)有處理拒絕訪(fǎng)問(wèn)異常,那就繼續(xù)往上個(gè)過(guò)濾器拋,就到了我們的異常翻譯過(guò)濾器 ExceptionTranslationFilter。ExceptionTranslationFilter

該過(guò)濾器的 doFilter() 方法很簡(jiǎn)單,沒(méi)有邏輯處理,只對(duì)后續(xù)過(guò)濾器拋出的異常進(jìn)行處理,源碼如下:

public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)throws IOException, ServletException {HttpServletRequest request = (HttpServletRequest) req;HttpServletResponse response = (HttpServletResponse) res;try {chain.doFilter(request, response);logger.debug('Chain processed normally');}catch (IOException ex) {throw ex;}catch (Exception ex) {// Try to extract a SpringSecurityException from the stacktraceThrowable[] causeChain = throwableAnalyzer.determineCauseChain(ex);RuntimeException ase = (AuthenticationException) throwableAnalyzer.getFirstThrowableOfType(AuthenticationException.class, causeChain);if (ase == null) {ase = (AccessDeniedException) throwableAnalyzer.getFirstThrowableOfType(AccessDeniedException.class, causeChain);}if (ase != null) {handleSpringSecurityException(request, response, chain, ase);}else {// Rethrow ServletExceptions and RuntimeExceptions as-isif (ex instanceof ServletException) {throw (ServletException) ex;}else if (ex instanceof RuntimeException) {throw (RuntimeException) ex;}// Wrap other Exceptions. This shouldn’t actually happen// as we’ve already covered all the possibilities for doFilterthrow new RuntimeException(ex);}}}

當(dāng)拋出拒絕訪(fǎng)問(wèn)異常后,繼續(xù)調(diào)用 handleSpringSecurityException(HttpServletRequest request, HttpServletResponse response, FilterChain chain, RuntimeException exception) 方法,方法里面主要將異常信息和錯(cuò)誤碼設(shè)置到響應(yīng)頭,然后響應(yīng)到客戶(hù)端,請(qǐng)求結(jié)束。

補(bǔ)充:權(quán)限表達(dá)式

權(quán)限表達(dá)式(ExpressionUrlAuthorizationConfigurer) 說(shuō)明 Spel表達(dá)式 Spel表達(dá)式實(shí)際執(zhí)行方法(SecurityExpressionOperations) permitAll() 表示允許所有,永遠(yuǎn)返回true permitAll permitAll() denyAll() 表示拒絕所有,永遠(yuǎn)返回false denyAll denyAll() anonymous() 當(dāng)前用戶(hù)是anonymous時(shí)返回true anonymous isAnonymous() rememberMe() 當(dāng)前用戶(hù)是rememberMe用戶(hù)時(shí)返回true rememberMe isRememberMe() authenticated() 當(dāng)前用戶(hù)不是anonymous時(shí)返回true authenticated isAuthenticated() fullyAuthenticated() 當(dāng)前用戶(hù)既不是anonymous也不是rememberMe用戶(hù)時(shí)返回true fullyAuthenticated isFullyAuthenticated() hasRole(“BUYER”) 用戶(hù)擁有指定權(quán)限時(shí)返回true hasRole(‘ROLE_BUYER’) hasRole(String role) hasAnyRole(“BUYER”,“SELLER”) 用于擁有任意一個(gè)角色權(quán)限時(shí)返回true hasAnyRole (‘ROLE_BUYER’,‘ROLE_BUYER’) hasAnyRole(String… roles) hasAuthority(“BUYER”) 同hasRole hasAuthority(‘ROLE_BUYER’) hasAuthority(String role) hasAnyAuthority(“BUYER”,“SELLER”) 同hasAnyRole hasAnyAuthority (‘ROLE_BUYER’,‘ROLE_BUYER’) hasAnyAuthority(String… authorities) hasIpAddress(‘192.168.1.0/24’) 請(qǐng)求發(fā)送的Ip匹配時(shí)返回true hasIpAddress(‘192.168.1.0/24’) hasIpAddress(String ipAddress),該方法在WebSecurityExpressionRoot類(lèi)中 access('@rbacService.hasPermission(request, authentication)') 可以自定義Spel表達(dá)式 @rbacService.hasPermission (request, authentication) hasPermission(request, authentication) ,該方法在自定義的RbacServiceImpl類(lèi)中 四、總結(jié) 訪(fǎng)問(wèn)控制的核心過(guò)濾器是 FilterSecurityInterceptor ,當(dāng)然這個(gè)是可選的,我們完全也可以自定義一個(gè)過(guò)濾器去處理權(quán)限訪(fǎng)問(wèn)。 處理訪(fǎng)問(wèn)異常處理的過(guò)濾器是 ExceptionTranslationFilter ,里面邏輯很簡(jiǎn)單,給response設(shè)置異常信息錯(cuò)誤碼,再返回給客戶(hù)端。

以上就是Spring Security源碼解析之權(quán)限訪(fǎng)問(wèn)控制是如何做到的的詳細(xì)內(nèi)容,更多關(guān)于Spring Security權(quán)限訪(fǎng)問(wèn)控制的資料請(qǐng)關(guān)注好吧啦網(wǎng)其它相關(guān)文章!

標(biāo)簽: Spring
相關(guān)文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
欧美激情三区| 91超碰国产精品| 久久中文视频| 亚洲二区在线| 91成人网在线观看| 国产视频一区三区| 日韩网站中文字幕| 国产精品亚洲一区二区三区在线观看| 久久精品国产一区二区| 久久精品国产亚洲aⅴ| 精品一区视频| 国产精品毛片久久| 欧美日韩免费看片| 欧美日韩一二三四| 午夜国产精品视频| 蜜桃免费网站一区二区三区| 日韩欧美高清一区二区三区| 国产欧美自拍一区| 精品精品国产三级a∨在线| 老司机精品视频网| 国产中文在线播放| 日韩国产网站| 亚洲免费一区二区| 日韩av成人高清| 里番精品3d一二三区| www.九色在线| 亚洲激情中文| 亚洲精品美女91| 国产精品啊啊啊| 日韩另类视频| 美女91精品| 日韩精品第一| 精品国产乱码久久久| 88xx成人免费观看视频库| 不卡视频在线| 欧美日韩99| 另类小说一区二区三区| 日韩中文视频| 亚洲精品一二三**| 高清日韩中文字幕| 国产亚洲在线观看| 国产精品qvod| 亚洲成人va| 亚洲精品九九| 欧美好骚综合网| 日韩中文字幕一区二区三区| 国产毛片精品| 亚洲一级高清| 欧美一区在线观看视频| 亚洲黄色免费看| 蜜臀av性久久久久蜜臀aⅴ四虎| 911亚洲精品| 国产精品99视频| 久久aⅴ国产紧身牛仔裤| 国产精品扒开腿做爽爽爽软件| 私拍精品福利视频在线一区| 婷婷精品在线| 天堂网av成人| 欧美日韩午夜电影网| 久久精品一区二区不卡| 日韩av一区二区三区| 久久精品国语| 国产精品theporn| 美女精品在线观看| 久久久久久久欧美精品| 激情婷婷欧美| 国产黄色精品| 视频一区欧美日韩| 麻豆传媒一区二区三区| 在线综合视频| 精品国产成人| 日韩精品免费视频一区二区三区| 99久久婷婷这里只有精品| 国产精品亚洲产品| 午夜久久久久| 国产一区福利| 亚洲精品伊人| 午夜国产精品视频免费体验区| 麻豆国产精品| 日韩精品三级| 亚洲一区欧美二区| 97精品国产| 国产伦一区二区三区| 女人天堂亚洲aⅴ在线观看| 美女在线视频一区| 美女久久一区| 亚洲福利免费| 91一区二区三区四区| 91精品福利观看| 水蜜桃久久夜色精品一区的特点| 亚洲播播91| 国产成年精品| 国产精品乱战久久久| 亚洲三级视频| 99在线精品免费视频九九视| 9999国产精品| 久久a爱视频| 欧美亚洲国产日韩| 日韩专区欧美专区| 午夜国产精品视频免费体验区| 夜鲁夜鲁夜鲁视频在线播放| 久久成人av| 国产精品久久乐| 欧美天堂一区| 欧美偷窥清纯综合图区| 日本中文字幕不卡| 亚洲乱亚洲高清| 午夜在线视频观看日韩17c| 精品一区欧美| 国产字幕视频一区二区| 欧美男人天堂| av资源新版天堂在线| 国产一区福利| 老牛国内精品亚洲成av人片| 久久国际精品| 人人爱人人干婷婷丁香亚洲| 亚洲精品福利| 深夜福利亚洲| 日韩国产欧美一区二区三区| 蜜芽一区二区三区| 亚洲精品观看| 久久国产免费看| 欧美黑人做爰爽爽爽| 麻豆精品久久久| 国产一区二区三区四区五区| 老色鬼精品视频在线观看播放| 精品国产一区二区三区性色av| 国产精品九九| 欧美经典一区| 国产成人久久精品一区二区三区| 精品一区二区三区视频在线播放 | 麻豆理论在线观看| 亚洲伊人av| 久久久精品午夜少妇| 久久国产直播| 99视频精品免费观看| 亚洲人成网77777色在线播放| 婷婷久久免费视频| 欧美日韩 国产精品| 欧美经典一区| 国产资源在线观看入口av| 日本精品影院| 国产亚洲欧洲| 四虎精品一区二区免费| 欧美在线观看天堂一区二区三区| 国产日韩一区二区三区在线| 免费亚洲婷婷| 精精国产xxxx视频在线播放| 亚洲一区欧美激情| 欧美天堂一区| xxxxx性欧美特大| 亚洲经典在线| 青青国产91久久久久久| 免费在线欧美黄色| 久久国产免费| 综合一区二区三区| 乱一区二区av| 免费精品国产| 日韩精品五月天| 成人精品高清在线视频| 黑丝一区二区| 国产精品最新| 亚洲成人一区在线观看| 国产精品人人爽人人做我的可爱 | 亚洲精选av| 免费一区二区三区在线视频| 久久天堂精品| 日韩中文字幕一区二区三区| 国产精品一区二区精品视频观看| 精品一区视频| 在线一区免费| 国产精品久久久久av蜜臀 | 日韩欧美激情| 韩国久久久久久| 夜夜嗨一区二区| 欧美天堂在线| 91精品国产福利在线观看麻豆| 日本欧美在线看| 久久亚洲黄色| 自拍日韩欧美| 欧美国产另类| 亚洲男女自偷自拍| 老司机精品视频网| 亚洲欧美网站| 国产a亚洲精品| 蜜臀av性久久久久蜜臀aⅴ流畅| 久久精品人人| 蜜臀国产一区二区三区在线播放| 毛片不卡一区二区| 亚洲在线一区| sm久久捆绑调教精品一区| 丝袜a∨在线一区二区三区不卡 | 精品欧美日韩精品| 99国产精品| 精品国产黄a∨片高清在线| 国产亚洲高清视频| 国产精品九九| 老牛影视一区二区三区| 精品国产亚洲一区二区三区在线 | 精品国产亚洲一区二区三区大结局 |