国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Spring Security之基于HttpRequest配置權(quán)限

這篇具有很好參考價(jià)值的文章主要介紹了Spring Security之基于HttpRequest配置權(quán)限。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

前言

今天我們重點(diǎn)聊聊授權(quán)方式的另外一種:基于HttpServletRequest配置權(quán)限

基于HttpServletRequest配置權(quán)限

一個(gè)典型的配置demo

http.authorizeHttpRequests(requestMatcherRegstry -> 
// /admin/** 需要有AMIND角色
	requestMatcherRegstry.requestMatchers("/admin/**").hasRole("ADMIN")
			// /log/** 只要有AMIND、USER角色之一
          .requestMatchers("/log/**").hasAnyRole("ADMIN", "USER")
			// 任意請(qǐng)求 只要登錄了即可訪問
          .anyRequest().authenticated()
);

從這里也可以看出,要實(shí)現(xiàn)基于RBAC,還是比較容易的。也比較容易使用。但是如果想要?jiǎng)討B(tài)的增加角色,就需要我們定制AuthorizationManager。

配置原理

HttpSecurity是負(fù)責(zé)構(gòu)建DefaultSecurityFilterChain的。而這個(gè)安全過濾器鏈,則是允許我們進(jìn)行配置的。而authorizeHttpRequests方法,正是配置AuthorizationFilter的。而我們傳入的入?yún)?lambada表達(dá)式-則是指引如何配置AuthorizationFilter的。

/**
 * 這個(gè)方法是HttpSecurity的方法。
 * 作用是配置AuthorizationFilter。
 * 其入?yún)uthorizeHttpRequestsCustomizer正是讓我們配置AuthorizationFilter的關(guān)鍵。
 * Customizer:就是定制。原理比較容易理解,就是我把你需要配置的東西丟給你,你往里面賦值。
 * AuthorizeHttpRequestsConfigurer<HttpSecurity>:這個(gè)是Configurer的實(shí)現(xiàn),負(fù)責(zé)引入過濾器的。這里明顯就是引入AuthorizationFilter
 * AuthorizationManagerRequestMatcherRegistry:這個(gè)就是我們最終配置的東西。而這個(gè)配置的正是我們上面的RequestMatcherDelegatingAuthorizationManager。說白了就是往里面添加哪些路徑對(duì)應(yīng)哪些AuthorizationManager。只不過,為了方便使用,也幫我們都封裝好了。不妨繼續(xù)往后看看。
 */
public HttpSecurity authorizeHttpRequests(
			Customizer<AuthorizeHttpRequestsConfigurer<HttpSecurity>.AuthorizationManagerRequestMatcherRegistry> authorizeHttpRequestsCustomizer)
			throws Exception {
		ApplicationContext context = getContext();
		// 這里干了三個(gè)事情:
		// 1. 如果當(dāng)前HttpSecurity不存在AuthorizeHttpRequestsConfigurer,則創(chuàng)建一個(gè),并注冊(cè)到當(dāng)前的HttpSecurity對(duì)象中。
		// 2. 從AuthorizeHttpRequestsConfigurer拿到他的注冊(cè)器也就是AuthorizationManagerRequestMatcherRegistry
		// 3. 調(diào)用傳入的參數(shù)的customize。如此,我們傳入的lambda表達(dá)式就被調(diào)用了。
		authorizeHttpRequestsCustomizer
			.customize(getOrApply(new AuthorizeHttpRequestsConfigurer<>(context)).getRegistry());
		return HttpSecurity.this;
	}
public final class AuthorizationManagerRequestMatcherRegistry
		extends AbstractRequestMatcherRegistry<AuthorizedUrl> {
	/**
	 * 這是父類的方法
	 * C代表的是AuthorizedUrl
	 */
	public C requestMatchers(String... patterns) {
		// 調(diào)用的重載方法第一個(gè)參數(shù)為HttpMethod,也就是說,我們還可以指定HTTP請(qǐng)求的方法,例如:POST、GET等
		return requestMatchers(null, patterns);
	}
	
	@Override
	protected AuthorizedUrl chainRequestMatchers(List<RequestMatcher> requestMatchers) {
		this.unmappedMatchers = requestMatchers;
		return new AuthorizedUrl(requestMatchers);
	}
}
public class AuthorizedUrl {
	private final List<? extends RequestMatcher> matchers;
	public AuthorizationManagerRequestMatcherRegistry permitAll() {
		return access(permitAllAuthorizationManager);
	}
	public AuthorizationManagerRequestMatcherRegistry hasRole(String role) {
		return access(withRoleHierarchy(AuthorityAuthorizationManager.hasRole(role)));
	}
	public AuthorizationManagerRequestMatcherRegistry hasAnyAuthority(String... authorities) {
		return access(withRoleHierarchy(AuthorityAuthorizationManager.hasAnyAuthority(authorities)));
	}
	public AuthorizationManagerRequestMatcherRegistry authenticated() {
		return access(AuthenticatedAuthorizationManager.authenticated());
	}
	public AuthorizationManagerRequestMatcherRegistry access(
		AuthorizationManager<RequestAuthorizationContext> manager) {
		Assert.notNull(manager, "manager cannot be null");
		return AuthorizeHttpRequestsConfigurer.this.addMapping(this.matchers, manager);
	}
}
public final class AuthorizeHttpRequestsConfigurer<H extends HttpSecurityBuilder<H>>
		extends AbstractHttpConfigurer<AuthorizeHttpRequestsConfigurer<H>, H> {
		
	private AuthorizationManagerRequestMatcherRegistry addMapping(List<? extends RequestMatcher> matchers,
		AuthorizationManager<RequestAuthorizationContext> manager) {
		for (RequestMatcher matcher : matchers) {
			this.registry.addMapping(matcher, manager);
		}
		return this.registry;
	}
}

我們通過lambda表達(dá)式:

requestMatcherRegstry -> requestMatcherRegstry.requestMatchers("/admin/**").hasRole("ADMIN")

配置的正是AuthorizationManagerRequestMatcherRegistry
requestMachers方法,構(gòu)建出AuthorizedUrl,然后通過這個(gè)類的hasRole方法注冊(cè)當(dāng)前路徑所對(duì)應(yīng)的權(quán)限/角色。這個(gè)對(duì)應(yīng)關(guān)系由RequestMatcherEntry保存。key:RequestMatcher requestMatcher;value: AuthorizationManager。

值得一提的是,這個(gè)lambda表達(dá)式以及其鏈?zhǔn)秸{(diào)用看起來簡(jiǎn)單方便,但是其內(nèi)部涉及多個(gè)類的方法調(diào)用,實(shí)在很容易犯迷糊,這是我覺得比較詬病的地方。在我看來,鏈?zhǔn)秸{(diào)用還是同一個(gè)返回值(每次都返回this)才能做到在方便至于也能清晰明了,容易理解。
而這里在lambda表達(dá)式內(nèi)部:

  • 第一個(gè)方法是requestMatcherRegstry.requestMatchers
    AbstractRequestMatcherRegistry,也就是我們的AuthorizationManagerRequestMatcherRegistry的父類。方法返回值是AuthorizedUrl。
  • 第二個(gè)方法是AuthorizedUrl.hasRole
    而該方法的返回值為AuthorizationManagerRequestMatcherRegistry。

發(fā)現(xiàn)什么了嗎?鏈?zhǔn)秸{(diào)用還能玩起遞歸,又回到最開始的第一個(gè)方法了。而要是我們配置HttpSecurity,直接一連串的鏈?zhǔn)秸{(diào)用,那更是沒譜了。經(jīng)常就是,你只能看著別人這樣配置,然后照貓畫虎。這個(gè)鏈?zhǔn)秸{(diào)用咋調(diào)回來的,一頭霧。因?yàn)橹虚g可能跨越好幾個(gè)不同的類。。。
PS:可能官方也有些意識(shí)到這點(diǎn),所以sample工程都是類似于本文開頭的那樣,傳入一個(gè)基于lambda表達(dá)式的Customizer。一個(gè)方法配置一個(gè)過濾器的SecurityConfigurer。但,如果你翻看源碼,你看到的就是一連串的鏈?zhǔn)秸{(diào)用。最為明顯的一個(gè)證明就是HttpSecurity#and方法過期了。因此個(gè)人推薦大家用文章開頭的那種方法,相對(duì)清晰易理解。

我想說,這么玩是深怕別人搞明白了是嗎???更絕的是,即便你知曉了原理也沒有辦法直接注冊(cè)對(duì)應(yīng)關(guān)系,除非你使用反射!

這里給大家提個(gè)醒,如果你想搞明白你在使用SpringSecurity究竟在配置些什么,那么你就必須要搞明白上面的套路。

設(shè)計(jì)方案

Spring Security在5.5版本之后,在鑒權(quán)架構(gòu)上,進(jìn)行了較大的改動(dòng)。以至于官方也出了遷移指南

組件 5.5之前 5.5之后
過濾器 FilterSecurityInterceptor AuthorizationFilter
鑒權(quán)管理器 AccessDecisionManager AuthorizationManager
訪問決策投票員 AccessDecisionVoter -

而原來的設(shè)計(jì)方案,相較于新的方案,更為復(fù)雜。這里給大家一張官方的UML感受感受:
authorizationmanagerrequestmatcherregistry,探索Spring Security,spring,springboot
除卻過濾器外,還需要三個(gè)組件來構(gòu)建完整的鑒權(quán):
AccessDecisionManager 、AccessDecisionVoter 、ConfigAttribute。

感興趣的同學(xué)可以自己琢磨琢磨,但已經(jīng)廢棄的方案,這里就不討論了。

5.6之后的新方案

新方案只有一個(gè)包羅萬象、且極具擴(kuò)展性的AuthorizationManager
authorizationmanagerrequestmatcherregistry,探索Spring Security,spring,springboot
我們前面的配置demo,本質(zhì)上都是在配置RequestMatcherDelegatingAuthorizationManager。他主要是記錄每一個(gè)路徑對(duì)應(yīng)的AuthorizationManager<HttpServletRequest>。當(dāng)有請(qǐng)求過來時(shí),只需要遍歷每一個(gè)路徑,當(dāng)找到匹配者就委托該AuthorizationManager<HttpServletRequest>進(jìn)行鑒權(quán)。

在我們的配置demo中,對(duì)應(yīng)的是AuthoriztyAuthorizationManagerAuthenticatedAuthorizationManager。前者,意味著我們配置的是角色/權(quán)限,后者對(duì)應(yīng)的是authenticated()這個(gè)方法。

如果你認(rèn)真看了這個(gè)關(guān)系圖,那么一定會(huì)發(fā)現(xiàn)右邊的4個(gè)實(shí)現(xiàn)類正是我們?cè)谏弦晃闹v述基于方法配置權(quán)限中所使用到的。

鑒權(quán)源碼分析

權(quán)限過濾的入口:AuthorizationFilter

public class AuthorizationFilter extends GenericFilterBean {

	@Override
	public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain)
			throws ServletException, IOException {
		// 類型轉(zhuǎn)換
		HttpServletRequest request = (HttpServletRequest) servletRequest;
		HttpServletResponse response = (HttpServletResponse) servletResponse;
		// 是否需要執(zhí)行鑒權(quán)
		if (this.observeOncePerRequest && isApplied(request)) {
			chain.doFilter(request, response);
			return;
		}
		// /error和異步請(qǐng)求不處理
		if (skipDispatch(request)) {
			chain.doFilter(request, response);
			return;
		}
		// 是否已經(jīng)執(zhí)行過鑒權(quán)邏輯了
		String alreadyFilteredAttributeName = getAlreadyFilteredAttributeName();
		request.setAttribute(alreadyFilteredAttributeName, Boolean.TRUE);
		try {
			// 從SecurityContextHolder中獲取憑證,并通過AuthorizationManager做出決策
			AuthorizationDecision decision = this.authorizationManager.check(this::getAuthentication, request);
			
			// 發(fā)布鑒權(quán)事件
			this.eventPublisher.publishAuthorizationEvent(this::getAuthentication, request, decision);
			if (decision != null && !decision.isGranted()) {
				// 拒絕訪問異常
				throw new AccessDeniedException("Access Denied");
			}
			// 正常執(zhí)行后續(xù)業(yè)務(wù)邏輯
			chain.doFilter(request, response);
		}
		finally {
			// 處理完業(yè)務(wù)邏輯后,為當(dāng)前請(qǐng)求清理標(biāo)識(shí)			
			request.removeAttribute(alreadyFilteredAttributeName);
		}
	}
}

RequestMatcherDelegatingAuthorizationManager

public final class RequestMatcherDelegatingAuthorizationManager implements AuthorizationManager<HttpServletRequest> {
@Override
	public AuthorizationDecision check(Supplier<Authentication> authentication, HttpServletRequest request) {
		// 遍歷每一個(gè)已經(jīng)登錄好的路徑,找到對(duì)應(yīng)的AuthorizationManager<RequestAuthorizationContext>>
		for (RequestMatcherEntry<AuthorizationManager<RequestAuthorizationContext>> mapping : this.mappings) {

			RequestMatcher matcher = mapping.getRequestMatcher();
			// 匹配當(dāng)前請(qǐng)求
			MatchResult matchResult = matcher.matcher(request);
			if (matchResult.isMatch()) {
				// 找到匹配的AuthorizationManager就直接調(diào)用check方法并返回鑒權(quán)結(jié)果
				AuthorizationManager<RequestAuthorizationContext> manager = mapping.getEntry();
				return manager.check(authentication,
						new RequestAuthorizationContext(request, matchResult.getVariables()));
			}
		}
		// 沒有匹配的AuthorizationManager則返回拒絕當(dāng)前請(qǐng)求
		return DENY;
	}
}

可見,在沒有匹配的AuthorizationManager的情況下,默認(rèn)是拒絕請(qǐng)求的。

總結(jié)

  1. 我們?cè)谂渲弥信渲玫膗rl被封裝成RequestMatcher,而hasRole被封裝成AuthorityAuthorizationManager。進(jìn)行注冊(cè),在請(qǐng)求過來時(shí),便通過遍歷所有注冊(cè)好的RequestMatch進(jìn)行匹配,存在匹配就調(diào)用AuthorizationManager<RequestAuthorizationContext>#check方法。

  2. 配置的鏈?zhǔn)秸{(diào)用,會(huì)跨越多個(gè)不同的類,最終又回到第一個(gè)對(duì)象的類型。

后記

本文我們聊了基于HttpRequest配置權(quán)限的方方面面。相信這里有一個(gè)點(diǎn)應(yīng)該會(huì)引起大家的注意:配置。下一次,我們聊聊Spring Security的配置體系。文章來源地址http://www.zghlxwxcb.cn/news/detail-847816.html

到了這里,關(guān)于Spring Security之基于HttpRequest配置權(quán)限的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 安全框架Spring Security是什么?如何理解Spring Security的權(quán)限管理?

    安全框架Spring Security是什么?如何理解Spring Security的權(quán)限管理?

    大家好,我是卷心菜。本篇主要講解Spring Security的基本介紹和架構(gòu)分析,如果您看完文章有所收獲,可以三連支持博主哦~,嘻嘻。 ?? 作者簡(jiǎn)介: 在校大學(xué)生一枚,Java領(lǐng)域新星創(chuàng)作者,Java、Python正在學(xué)習(xí)中,期待和大家一起學(xué)習(xí)一起進(jìn)步~ ?? 個(gè)人主頁:我是一棵卷心菜的

    2024年02月02日
    瀏覽(24)
  • 13.Spring security權(quán)限管理

    13.Spring security權(quán)限管理

    13.1什么是權(quán)限管理 Spring security支持多種不同的認(rèn)證方式,但是無論開發(fā)者使用哪種認(rèn)證方式,都不會(huì)影響授權(quán)功能的使用,spring security很好地實(shí)現(xiàn)了認(rèn)證和授權(quán)兩大功能的解耦。 13.2Spring security權(quán)限管理策略 從技術(shù)上來說,spring security中提供的權(quán)限管理功能主要有兩種類型

    2023年04月12日
    瀏覽(16)
  • 【Spring Security系列】一文帶你了解權(quán)限框架與Spring Security核心概念

    【Spring Security系列】一文帶你了解權(quán)限框架與Spring Security核心概念

    權(quán)限框架是軟件開發(fā)中用于管理 用戶權(quán)限和訪問控制 的工具。在企業(yè)或者我們畢設(shè)復(fù)雜的系統(tǒng)中,不同的用戶或角色需要擁有不同的訪問和操作權(quán)限,以確保系統(tǒng)的安全性和數(shù)據(jù)完整性。今天我們就討論一下Java中的安全框架! 在企業(yè)的開發(fā)中,Spring Security,Shiro都是比較流

    2024年04月16日
    瀏覽(18)
  • SpringBoot整合Spring Security實(shí)現(xiàn)權(quán)限控制

    SpringBoot整合Spring Security實(shí)現(xiàn)權(quán)限控制

    要對(duì)Web資源進(jìn)行保護(hù),最好的辦法莫過于Filter 要想對(duì)方法調(diào)用進(jìn)行保護(hù),最好的辦法莫過于AOP。 Spring Security進(jìn)行認(rèn)證和鑒權(quán)的時(shí)候,就是利用的一系列的Filter來進(jìn)行攔截的。 如圖所示,一個(gè)請(qǐng)求想要訪問到API就會(huì)從左到右經(jīng)過藍(lán)線框里的過濾器,其中 綠色部分是負(fù)責(zé)認(rèn)證的

    2024年02月15日
    瀏覽(17)
  • Spring Security--守護(hù)你的功能權(quán)限

    首先,讓我們明確一下什么是Spring Security以及前后端分離路徑攔截器。Spring Security是一個(gè)基于Spring框架的安全框架,它提供了一系列的安全服務(wù),包括但不限于認(rèn)證、授權(quán)、加密和會(huì)話管理等。而前后端分離路徑攔截器是指在前后端分離的情況下,根據(jù)用戶角色和權(quán)限對(duì)請(qǐng)求

    2024年02月06日
    瀏覽(21)
  • Spring Security 中自定義權(quán)限表達(dá)式

    Spring Security 中自定義權(quán)限表達(dá)式

    前言 這是我在這個(gè)網(wǎng)站整理的筆記,有錯(cuò)誤的地方請(qǐng)指出,關(guān)注我,接下來還會(huì)持續(xù)更新。 作者:神的孩子都在歌唱 通過編程授權(quán)方法 首先,聲明一個(gè) Bean,如下所示: 然后,在注解中以如下方式引用該 Bean: Spring Security 將在每次方法調(diào)用時(shí)調(diào)用該Bean上的給定方法。 這樣

    2024年02月06日
    瀏覽(36)
  • Spring Security實(shí)現(xiàn)用戶身份驗(yàn)證及權(quán)限管理

    Spring Security實(shí)現(xiàn)用戶身份驗(yàn)證及權(quán)限管理

    Spring Security是Spring生態(tài)的一個(gè)成員,提供了一套Web應(yīng)用安全性的完整解決方案。 Spring Security 旨在以一種自包含的方式進(jìn)行操作,因此你不需要在 Java 運(yùn)行時(shí)環(huán)境中放置任何特殊的配置文件。這種設(shè)計(jì)使部署極為方便,因?yàn)榭梢詫⒛繕?biāo) 工件 (無論是 JAR還是WAR)從一個(gè)系統(tǒng)復(fù)

    2024年02月05日
    瀏覽(21)
  • 【業(yè)務(wù)功能篇57】Springboot + Spring Security 權(quán)限管理 【上篇】

    【業(yè)務(wù)功能篇57】Springboot + Spring Security 權(quán)限管理 【上篇】

    4.1.1 權(quán)限管理的意義 后臺(tái)管理系統(tǒng)中,通常需要控制不同的登錄用戶可以操作的內(nèi)容。權(quán)限管理用于管理系統(tǒng)資源,分配用戶菜單、資源權(quán)限,以及驗(yàn)證用戶是否有訪問資源權(quán)限。 4.1.2 RBAC權(quán)限設(shè)計(jì)模型 ACL介紹 ACL(Access Control List):訪問控制列表 用戶 - 權(quán)限 ACL 模型,權(quán)限

    2024年02月15日
    瀏覽(26)
  • 微服務(wù)動(dòng)態(tài)權(quán)限管理方案(Spring Cloud Gateway+Spring Cloud Security)

    微服務(wù)動(dòng)態(tài)權(quán)限管理方案(Spring Cloud Gateway+Spring Cloud Security)

    微服務(wù)認(rèn)證方案的大體方向是統(tǒng)一在網(wǎng)關(guān)層面認(rèn)證鑒權(quán),微服務(wù)只負(fù)責(zé)業(yè)務(wù),和鑒權(quán)完全隔離 整體包含以下四個(gè)角色 客戶端 :需要訪問微服務(wù)資源 網(wǎng)關(guān) :負(fù)責(zé)轉(zhuǎn)發(fā)、認(rèn)證、鑒權(quán) OAuth2.0授權(quán)服務(wù) :負(fù)責(zé)認(rèn)證授權(quán)頒發(fā)令牌 微服務(wù)集合 :提供資源的一系列服務(wù)。 這里的客戶端

    2024年02月12日
    瀏覽(21)
  • Spring Security安全登錄的調(diào)用過程以及獲取權(quán)限的調(diào)用過程

    Spring Security安全登錄的調(diào)用過程以及獲取權(quán)限的調(diào)用過程

    (0)權(quán)限授理 首先調(diào)用SecurityConfig.java中的config函數(shù)將jwtAuthenticationTokenFilter過濾器放在UsernamePasswordAuthenticationFilter之前 (1)首先運(yùn)行JwtAuthenticationTokenFilter extends OncePerRequestFilter中的doFilterInternal函數(shù) 這里由于沒有獲取到token,因此調(diào)用!StringUtils.hasText(token),這里使用 繼續(xù)運(yùn)行其他

    2024年02月09日
    瀏覽(20)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包