欧美一区二区三区老妇人-欧美做爰猛烈大尺度电-99久久夜色精品国产亚洲a-亚洲福利视频一区二区

SpringSecurity原理是什么

本篇內(nèi)容主要講解“SpringSecurity原理是什么”,感興趣的朋友不妨來(lái)看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來(lái)帶大家學(xué)習(xí)“SpringSecurity原理是什么”吧!

成都創(chuàng)新互聯(lián)主要為客戶提供服務(wù)項(xiàng)目涵蓋了網(wǎng)頁(yè)視覺設(shè)計(jì)、VI標(biāo)志設(shè)計(jì)、網(wǎng)絡(luò)營(yíng)銷推廣、網(wǎng)站程序開發(fā)、HTML5響應(yīng)式重慶網(wǎng)站建設(shè)公司手機(jī)網(wǎng)站制作設(shè)計(jì)、微商城、網(wǎng)站托管及成都網(wǎng)站維護(hù)公司、WEB系統(tǒng)開發(fā)、域名注冊(cè)、國(guó)內(nèi)外服務(wù)器租用、視頻、平面設(shè)計(jì)、SEO優(yōu)化排名。設(shè)計(jì)、前端、后端三個(gè)建站步驟的完善服務(wù)體系。一人跟蹤測(cè)試的建站服務(wù)標(biāo)準(zhǔn)。已經(jīng)為門窗定制行業(yè)客戶提供了網(wǎng)站開發(fā)服務(wù)。

SpringSecurity 原理解析【3】:認(rèn)證與授權(quán)

在上篇文章中提到構(gòu)建SecurityFilterChain過(guò)程中存在一個(gè)方法級(jí)別的過(guò)濾器:FilterSecurityInterceptor。該過(guò)濾器統(tǒng)一調(diào)用了認(rèn)證和授權(quán)兩種功能,而Spring Security主要就做這2件事,1: 身份認(rèn)證(誰(shuí)在發(fā)起請(qǐng)求),2:身份授權(quán)(是否有權(quán)限訪問(wèn)資源)。但是需要明確一點(diǎn):FilterSecurityInterceptor主要做的是基于訪問(wèn)規(guī)則的身份授權(quán)。而身份認(rèn)證是身份授權(quán)的前提,因此FilterSecurityInterceptor會(huì)在認(rèn)證信息不存在時(shí)進(jìn)行一次身份認(rèn)證。正常認(rèn)證流程是在其他優(yōu)先級(jí)更高的過(guò)濾器完成的身份認(rèn)證,當(dāng)然二者的認(rèn)證流程一致:

  • 通過(guò)AuthenticationManager獲取當(dāng)前請(qǐng)求的身份認(rèn)證信息

  • 通過(guò)AccessDecisionManager決斷特定訪問(wèn)規(guī)則的web資源能否被訪問(wèn)

身份認(rèn)證

身份認(rèn)證就是辨別出當(dāng)前請(qǐng)求是誰(shuí)發(fā)出的。在Spring Security中,哪怕不需要知道某個(gè)請(qǐng)求是誰(shuí)發(fā)出的,也會(huì)給這個(gè)請(qǐng)求的來(lái)源構(gòu)建一個(gè)身份信息:匿名身份。

對(duì)于需要知道請(qǐng)求的身份信息的,則需要客戶端提供身份標(biāo)識(shí)碼和開發(fā)者提供身份識(shí)別檔案信息,二者比對(duì)之后才能做出到底是哪個(gè)具體身份的決斷。客戶端提供的身份標(biāo)識(shí)被抽象為令牌Token,提供身份檔案信息的方式抽象為:認(rèn)證提供者AuthenticationProvider。

身份識(shí)別令牌

一個(gè)完整的身份識(shí)別令牌應(yīng)該能展示以下信息:令牌所屬人:Principal、所屬人的身份認(rèn)證憑證:Credentials、 所屬人附加信息:Details、所屬人的權(quán)限信息:Authorities。在Spring Security中使用Authentication表示

public interface Authentication extends Principal, Serializable {
    // 授權(quán)集合:GrantedAuthority實(shí)現(xiàn)類
    Collection<? extends GrantedAuthority> getAuthorities();
    // 憑證:【密碼】
    Object getCredentials();
    // 詳情:【其他信息】
    Object getDetails();
    // 主體:【賬號(hào)】  
    Object getPrincipal();
    // 是否已認(rèn)證:true為已認(rèn)證
    boolean isAuthenticated();
    // 設(shè)置是否已認(rèn)證:
    void setAuthenticated(boolean var1) throws IllegalArgumentException;
}

客戶端不能提供完整的身份識(shí)別令牌,因?yàn)榭蛻舳说男畔⒉⒉豢煽浚虼艘话愣钥蛻舳瞬恍枰峁┩暾牧钆菩畔ⅲ恍枰峁┠茏R(shí)別出所屬人Principal的識(shí)別碼即可,剩余的信息交給服務(wù)端去填充。Spring Security的身份認(rèn)證過(guò)程就是對(duì)身份識(shí)別令牌的填充過(guò)程。

所有的令牌都是Authentication的子類,令牌提供所屬人識(shí)別碼來(lái)填充完整令牌所屬人信息。根據(jù)令牌識(shí)別碼的提供方式不同,令牌實(shí)現(xiàn)也不同,常見提供方式有:賬號(hào)密碼、手機(jī)號(hào)、Cookie、Jwt、第三方授權(quán)碼、圖形驗(yàn)證碼等等。而Spring Security中內(nèi)置的令牌具有:RememberMeAuthenticationToken(靜默登錄令牌)、AnonymousAuthenticationToken(匿名訪問(wèn)令牌)、UsernamePasswordAuthenticationToken(賬號(hào)密碼令牌)、PreAuthenticatedAuthenticationToken(提前認(rèn)證令牌)、RunAsUserToken(身份轉(zhuǎn)換令牌)等

以賬號(hào)密碼令牌為例

Spring Security對(duì)賬號(hào)密碼令牌的支持為:UsernamePasswordAuthenticationToken,想使用該令牌進(jìn)行身份識(shí)別需要在SecurityFilterChain中添加UsernamePasswordAuthenticationFilter。當(dāng)然配置方式還是在HttpSecurity處配置

@Override
protected void configure(HttpSecurity http) throws Exception {
	http
			.authorizeRequests()
			// 登錄頁(yè)不需要權(quán)限就能訪問(wèn)
			.antMatchers("/login.html").permitAll()
			.anyRequest().authenticated()
			.and()
			// 使用UsernamePasswordAuthenticationToken作為客戶端使用的身份識(shí)別令牌
			.formLogin()
			// 登錄頁(yè)面
			.loginPage("/login.html")
			// 進(jìn)行身份識(shí)別匹配的路徑,這是一個(gè)POST方式的請(qǐng)求匹配器
			.loginProcessingUrl("/doLogin")
			// 身份識(shí)別成功之后的重定向展示頁(yè)面
			.defaultSuccessUrl("/home.html",false)
			// 身份識(shí)別失敗之后的重定向提示頁(yè)面
			.failureUrl("/login.html?error=1")
			.and()
			.logout()
	;
}

無(wú)論何種令牌,都需指定進(jìn)行認(rèn)證操作的請(qǐng)求路徑:AuthenticationURL。在賬號(hào)密碼令牌中,該認(rèn)證路徑使用loginProcessingUrl屬性配置,并默認(rèn)為POST方式的AntPathRequestMatcher。該匹配器在父類AbstractAuthenticationProcessingFilter中,通過(guò)requiresAuthentication來(lái)判斷是否需要認(rèn)證。如果當(dāng)前請(qǐng)求是匹配的認(rèn)證路徑,則認(rèn)證方法如下:

Authentication authResult = attemptAuthentication(request, response);

UsernamePasswordAuthenticationFilter實(shí)現(xiàn)簡(jiǎn)化為

public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
	// 請(qǐng)求中獲取參數(shù)
	String username = obtainUsername(request);
	String password = obtainPassword(request);
	// 構(gòu)建令牌
	UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);
	// 設(shè)置Details
	setDetails(request, authRequest);
	// 認(rèn)證入口:AuthenticationManager#authenticate
	return this.getAuthenticationManager().authenticate(authRequest);
}

無(wú)論何種令牌,在初步構(gòu)建之后都會(huì)交給AuthenticationManager#authenticate來(lái)完成認(rèn)證。這里就引入了Spring Security的身份認(rèn)證核心對(duì)象:認(rèn)證管理器:AuthenticationManager。可以這么理解:處理好了客戶端的非完整令牌,那么服務(wù)端就需要來(lái)逐步完善這個(gè)令牌。認(rèn)證管理器作為總的管理者,統(tǒng)一管理入口。

ProviderManager

AuthenticationManager是一個(gè)接口規(guī)范,其實(shí)現(xiàn)類為:ProviderManager,提供者管理器:管理能提供身份檔案信息的對(duì)象(AuthenticationProvider),能證明令牌確確實(shí)是屬于某個(gè)身份,能證明的方式有很多,Spring Security不是多方驗(yàn)證,而是首次驗(yàn)證成功即可,也就是說(shuō)雖然有很多方式能證明令牌真的屬于誰(shuí),但是Spring Security只需要一個(gè)能提供證明身份證明的檔案即可。ProviderManager是一個(gè)父子分層結(jié)構(gòu),如果都不能證明則會(huì)去父管理器中去證明。ProviderManager主要結(jié)構(gòu)如下

public class ProviderManager implements AuthenticationManager, 
	MessageSourceAware,
    InitializingBean {
	...
	// 管理多個(gè)AuthenticationProvider(認(rèn)證提供者)
	private List<AuthenticationProvider> providers = Collections.emptyList();
	// 父管理器
    private AuthenticationManager parent;
	...
}
AuthenticationProvider

AuthenticationProvider作為一個(gè)能提供身份檔案信息的接口規(guī)范,主要規(guī)范認(rèn)證功能,針對(duì)特定令牌提供supports功能,而且基于職責(zé)單一原則,每種Token都會(huì)有一個(gè)AuthenticationProvider實(shí)現(xiàn)。

public interface AuthenticationProvider {
	
	// Token令牌身份識(shí)別
	Authentication authenticate(Authentication authentication) throws AuthenticationException;
	// 是否支持某種類型的Token令牌
	boolean supports(Class<?> authentication);
}

以賬號(hào)密碼認(rèn)證提供者為例

此種令牌是客戶端提供賬號(hào)、密碼來(lái)作為識(shí)別碼進(jìn)行身份識(shí)別的認(rèn)證方式,因此服務(wù)端應(yīng)該會(huì)有一個(gè)存儲(chǔ)大量賬號(hào)、密碼和其他信息的地方。Spring Security將一個(gè)能存儲(chǔ)用戶認(rèn)證信息的對(duì)象抽象為:UserDetails。

public interface UserDetails extends Serializable {
    //授權(quán)集合
    Collection<? extends GrantedAuthority> getAuthorities();
    // 密碼
    String getPassword();
    //賬號(hào)
    String getUsername();
    //賬號(hào)是否過(guò)期
    boolean isAccountNonExpired();        //認(rèn)證前置校驗(yàn)
    //賬號(hào)是否鎖定
    boolean isAccountNonLocked();         //認(rèn)證前置校驗(yàn)
    // 憑證是否過(guò)期
    boolean isCredentialsNonExpired();    //認(rèn)證后置校驗(yàn)
    //賬號(hào)是否禁用
    boolean isEnabled();                  //認(rèn)證前置校驗(yàn)
}

認(rèn)證提供者需要做的就是從存儲(chǔ)的庫(kù)中找到對(duì)應(yīng)的UserDetails。DaoAuthenticationProvider就是通過(guò)數(shù)據(jù)訪問(wèn)(Data Access Object)來(lái)獲取到認(rèn)證對(duì)象的檔案信息的。獲取的實(shí)現(xiàn)交給了開發(fā)者,實(shí)現(xiàn)UserDetailsService#loadUserByUsername方法

UserDetails loadedUser = this.getUserDetailsService().loadUserByUsername(username);

獲取到UserDetails就可以去認(rèn)證了,流程簡(jiǎn)化如下

public Authentication authenticate(Authentication authentication) throws AuthenticationException {
	// 矯正賬戶名
	String username = (authentication.getPrincipal() == null) ? "NONE_PROVIDED" : authentication.getName();
	// 獲取認(rèn)證憑證
	UserDetails user = this.getUserDetailsService().loadUserByUsername(username);
	// 前置賬號(hào)檢測(cè):是否上鎖:LockedException,是否禁用:DisabledException,是否失效:AccountExpiredException
	preAuthenticationChecks.check(user);
	// 主體檢測(cè):抽象方法:默認(rèn)為密碼匹配檢測(cè)
	additionalAuthenticationChecks(user,(UsernamePasswordAuthenticationToken) authentication);
	// 后置憑證檢測(cè):憑證是否失效:CredentialsExpiredException
	postAuthenticationChecks.check(user);
    // 返回填充完整的令牌
    return createSuccessAuthentication(principalToReturn, authentication, user);
}

完整的令牌是UsernamePasswordAuthenticationToken的一個(gè)新的實(shí)例,各種認(rèn)證信息齊全。

令牌完整后續(xù)處理

身份識(shí)別成之后就會(huì)得到一個(gè)完整的令牌。后續(xù)則會(huì)處理Session(會(huì)話相關(guān))、Security Context(上下文相關(guān))、RememberMe(靜默登錄相關(guān))、SuccessHandler(成功之后跳轉(zhuǎn)相關(guān))

至此身份認(rèn)證流程完畢,登錄成功之后一般都會(huì)根據(jù)SuccessHandler跳轉(zhuǎn)的固定頁(yè)面,從而開啟訪問(wèn)授權(quán)決斷相關(guān)流程。認(rèn)證流程圖示如下:

SpringSecurity原理是什么

身份授權(quán)

身份認(rèn)證成功就能夠判斷令牌屬于誰(shuí),身份授權(quán)則判斷該身份能否訪問(wèn)指定資源。在上篇文章說(shuō)了SecurityFilterChain的構(gòu)建來(lái)源,除了被忽略的認(rèn)證和被其他過(guò)濾器攔截的,剩下的基本都是基于安全訪問(wèn)規(guī)則(ConfigAttribute)的判斷了。判斷入口在FilterSecurityInterceptor#invoke

安全訪問(wèn)規(guī)則:ConfigAttribute

從代碼中收集安全訪問(wèn)規(guī)則,主要存在以下類型

  • WebExpressionConfigAttribute


    基于Web表達(dá)式的訪問(wèn)規(guī)則,目前只有一個(gè)來(lái)源:ExpressionUrlAuthorizationConfigurer,HttpSecurity默認(rèn)使用的就是該類

    http.authorizeRequests()
            .antMatchers("/index").access("hasAnyRole('ANONYMOUS', 'USER')")
            .antMatchers("/login/*").access("hasAnyRole('ANONYMOUS', 'USER')")

  • SecurityConfig


    基于配置類的訪問(wèn)規(guī)則,常規(guī)用法基本都是該對(duì)象,例如@Secured、@PermitAll、@DenyAll 和 UrlAuthorizationConfigurer(HttpSecurity可配置)

    @GetMapping("/{id}")
    @PermitAll()
    public Result<Integer> find(@PathVariable Long id) {
    	return Result.success(service.find(id));
    }

  • PreInvocationExpressionAttribute


    基于AOP前置通知表達(dá)式的訪問(wèn)規(guī)則,主要是對(duì)@PreFilter 和 @PreAuthorize,這也是最常用的

    @DeleteMapping("/{id}")
    @PreAuthorize("hasAuthority('del')")
    public Result<Boolean> deleteById(@PathVariable Long id) {
    	return Result.success(service.deleteById(id));
    }

  • PostInvocationExpressionAttribute


    基于AOP后置通知調(diào)用表達(dá)式的訪問(wèn)規(guī)則,主要是對(duì)@PostFilter 和 @PostAuthorize

    @GetMapping("/{id}")
    @PostAuthorize("returnObject.data%2==0")
    public Result<Integer> find(@PathVariable Long id) {
    	return Result.success(service.find(id));
    }

授權(quán)模型

為了便于開發(fā),設(shè)計(jì)的安全訪問(wèn)規(guī)則來(lái)源有好幾種,不同的安全訪問(wèn)規(guī)則需要不同的處理機(jī)制來(lái)解析。能對(duì)某種安全訪問(wèn)規(guī)則做出當(dāng)前請(qǐng)求能否通過(guò)該規(guī)則并訪問(wèn)到資源的決斷的對(duì)象在Spring Security中抽象為AccessDecisionVoter:選民,做出決斷的動(dòng)作稱為:vote:投票。AccessDecisionVoter只能對(duì)支持的安全訪問(wèn)規(guī)則做出贊成、反對(duì)、棄權(quán)之一的決斷,每個(gè)決斷1個(gè)權(quán)重。接口規(guī)范如下:

public interface AccessDecisionVoter<S> {
	
	// 贊成票
	int ACCESS_GRANTED = 1;
	// 棄權(quán)票
	int ACCESS_ABSTAIN = 0;
	// 反對(duì)票
	int ACCESS_DENIED = -1;

	/**
	 *	是否支持對(duì)某配置數(shù)據(jù)進(jìn)行投票 
	 */
	boolean supports(ConfigAttribute attribute);

	/**
	 * 是否支持對(duì)某類型元數(shù)據(jù)進(jìn)行投票 
	 */
	boolean supports(Class<?> clazz);

	/**
	 *  對(duì)認(rèn)證信息進(jìn)行投票
	 */
	int vote(Authentication authentication, S object,Collection<ConfigAttribute> attributes);
}

Spring Security中對(duì)安全訪問(wèn)規(guī)則的最終決斷是基于投票結(jié)果然后根據(jù)決策方針才做出的結(jié)論。能做出最終決斷的接口為:AccessDecisionManager。

// 做出最終決斷的方法#
void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes) 
  throws AccessDeniedException, InsufficientAuthenticationException;

抽象實(shí)現(xiàn)為AbstractAccessDecisionManager,他管理多個(gè)選民AccessDecisionVoter

private List<AccessDecisionVoter<?>> decisionVoters;

AbstractAccessDecisionManager,具體類為決策方針,目前有三大方針,默認(rèn)為:一票通過(guò)方針:AffirmativeBased

決策方針

AffirmativeBased【一票通過(guò)方針】
public void decide(Authentication authentication, Object object,Collection<ConfigAttribute> configAttributes) throws AccessDeniedException {
	...
	for (AccessDecisionVoter voter : getDecisionVoters()) {
		int result = voter.vote(authentication, object, configAttributes);
		switch (result) {
		// 一票同意
		case AccessDecisionVoter.ACCESS_GRANTED:
			return;
		...
	}
}
ConsensusBased【少數(shù)服從多數(shù)方針】
public void decide(Authentication authentication, Object object,Collection<ConfigAttribute> configAttributes) throws AccessDeniedException {
	...
	for (AccessDecisionVoter voter : getDecisionVoters()) {
		int result = voter.vote(authentication, object, configAttributes);
		switch (result) {
		case AccessDecisionVoter.ACCESS_GRANTED: grant++; break;
		case AccessDecisionVoter.ACCESS_DENIED: deny++; break;
		default: break;
		}
	}
	// 多數(shù)同意才有效
	if (grant > deny) {
		return;
	}
	// 少數(shù)同意,決策無(wú)效
	if (deny > grant) {
		throw new AccessDeniedException(messages.getMessage("AbstractAccessDecisionManager.accessDenied", "Access is denied"));
	}
	// 票數(shù)相等則根據(jù)allowIfEqualGrantedDeniedDecisions來(lái)決定是否通過(guò)
	if ((grant == deny) && (grant != 0)) {
		if (this.allowIfEqualGrantedDeniedDecisions) {
			return;
		}
		else {
			throw new AccessDeniedException(messages.getMessage(
					"AbstractAccessDecisionManager.accessDenied", "Access is denied"));
		}
	}
	...
}
UnanimousBased【一票否決方針】
public void decide(Authentication authentication, Object object,Collection<ConfigAttribute> attributes) throws AccessDeniedException {
	...
	for (AccessDecisionVoter voter : getDecisionVoters()) {
		int result = voter.vote(authentication, object, singleAttributeList);
		switch (result) {
        ...
		// 一票否決
		case AccessDecisionVoter.ACCESS_DENIED:
			throw new AccessDeniedException(messages.getMessage(
					"AbstractAccessDecisionManager.accessDenied",
					"Access is denied"));
		...
	}
	...
}

選民類型


決策方針的執(zhí)行需要選民參與投票,三大決策都是通過(guò)遍歷decisionVoters來(lái)統(tǒng)計(jì)vote結(jié)果的。不同的decisionVoter解析不同的安全訪問(wèn)規(guī)則,因此當(dāng)一個(gè)訪問(wèn)規(guī)則需要決斷時(shí),只有支持當(dāng)前訪問(wèn)規(guī)則的decisionVoter才能做出決斷。因此需要知道一個(gè)訪問(wèn)規(guī)則會(huì)被哪種decisionVoter解析

基于角色的選民【RoleVoter】

針對(duì)具有角色權(quán)限標(biāo)識(shí)的安全訪問(wèn)規(guī)則進(jìn)行投票,角色權(quán)限標(biāo)識(shí)特征:private String rolePrefix = "ROLE_";,在Spring Security中角色權(quán)限都是該字符前綴,當(dāng)對(duì)用戶是否擁有該角色權(quán)限時(shí),就需要通過(guò)RoleVoter進(jìn)行投票,注:前綴可配置

public int vote(Authentication authentication, Object object, Collection<ConfigAttribute> attributes) {
	if (authentication == null) {
		return ACCESS_DENIED;
	}
	int result = ACCESS_ABSTAIN;
	// 從Token令牌中提取已授權(quán)集合
	Collection<? extends GrantedAuthority> authorities = extractAuthorities(authentication);
	// 先判斷選民是否支持對(duì)該屬性進(jìn)行投票
	for (ConfigAttribute attribute : attributes) {
		if (this.supports(attribute)) {
			result = ACCESS_DENIED;
			// 當(dāng)支持時(shí),則從已授權(quán)集合中獲取到該權(quán)限標(biāo)識(shí),如果獲取不到則表示無(wú)權(quán)限,投反對(duì)票
			// 已授權(quán)集合在身份認(rèn)證時(shí)已獲取
			for (GrantedAuthority authority : authorities) {
				if (attribute.getAttribute().equals(authority.getAuthority())) {
					return ACCESS_GRANTED;
				}
			}
		}
	}
	return result;
}
基于角色分級(jí)的選民【RoleHierarchyVoter】

在RoleVoter基礎(chǔ)上,將角色分級(jí),高級(jí)別的角色將自動(dòng)擁有低級(jí)別角色的權(quán)限,使用方式為角色名稱之間通過(guò)大于號(hào)“>”分割,前面的角色自動(dòng)擁有后面角色的權(quán)限

@Override
Collection<? extends GrantedAuthority> extractAuthorities( Authentication authentication) {
	// 提取權(quán)限集合時(shí),會(huì)將低級(jí)別角色的權(quán)限也獲取到
	return roleHierarchy.getReachableGrantedAuthorities(authentication.getAuthorities());
}

分割方法

String[] roles = line.trim().split("\\s+>\\s+");
基于認(rèn)證令牌的選民【AuthenticatedVoter】

針對(duì)固定的權(quán)限標(biāo)識(shí)進(jìn)行投票,這種標(biāo)識(shí)有三個(gè):全權(quán)授權(quán):IS_AUTHENTICATED_FULLY、RememberMe授權(quán)

IS_AUTHENTICATED_REMEMBERED、匿名訪問(wèn)授權(quán)

IS_AUTHENTICATED_ANONYMOUSLY。但是每種權(quán)限需要指定的Token才能投贊成票,這里引入了AuthenticationTrustResolver,主要就是判斷是否為Anonymous或者RememberMe

IS_AUTHENTICATED_REMEMBERED:需要認(rèn)證令牌為:RememberMeAuthenticationToken或者其子類(AuthenticationTrustResolver默認(rèn)實(shí)現(xiàn)),才能對(duì)該標(biāo)識(shí)投贊成票

IS_AUTHENTICATED_ANONYMOUSLY:需要認(rèn)證令牌為:AnonymousAuthenticationToken或者其子類(AuthenticationTrustResolver默認(rèn)實(shí)現(xiàn)),才能對(duì)該標(biāo)識(shí)投贊成票

IS_AUTHENTICATED_FULLY:需要認(rèn)證令牌不是以上兩種令牌,才能對(duì)該標(biāo)識(shí)投贊成票

基于Web表達(dá)式的選民【W(wǎng)ebExpressionVoter】

針對(duì)于Web表達(dá)式的權(quán)限控制,表達(dá)式的解析處理器為SecurityExpressionHandler,解析時(shí)使用的是SPEL解析器:SpelExpressionParser。

SecurityExpressionHandler能對(duì)以上所有投票方式進(jìn)行解析,解析結(jié)果為Boolean,true則表示贊成,false則表示反對(duì)

// 只支持Web表達(dá)式的屬性
public boolean supports(ConfigAttribute attribute) {
	return attribute instanceof WebExpressionConfigAttribute;
}
// 只支持FilterInvocation類型
public boolean supports(Class<?> clazz) {
	return FilterInvocation.class.isAssignableFrom(clazz);
}
前置調(diào)用增強(qiáng)的投票者【PreInvocationAuthorizationAdviceVoter】

同樣是基于SPEL表達(dá)式,但該表達(dá)式只針對(duì)方法級(jí)別的@PreFilter 和 @PreAuthorize,解析器為:MethodSecurityExpressionHandler。

public int vote(Authentication authentication, MethodInvocation method, Collection<ConfigAttribute> attributes) {
	// @PreFilter 和 @PreAuthorize增強(qiáng)獲取
	PreInvocationAttribute preAttr = findPreInvocationAttribute(attributes);
	if (preAttr == null) {
		return ACCESS_ABSTAIN;
	}
	// EL表達(dá)式解析 
	boolean allowed = preAdvice.before(authentication, method, preAttr);
	// 解析結(jié)果投票
	return allowed ? ACCESS_GRANTED : ACCESS_DENIED;
}
基于Jsr250規(guī)范的投票者【Jsr250Voter】

針對(duì)Jsr250規(guī)范的注解@PermitAll和@DenyAll控制的權(quán)限,前置投贊成票,后置投反對(duì)票。對(duì)于supports的權(quán)限投贊成票

public int vote(Authentication authentication, Object object, Collection<ConfigAttribute> definition) {
	boolean jsr250AttributeFound = false;
	for (ConfigAttribute attribute : definition) {
		//@PermitAll 贊成
		if (Jsr250SecurityConfig.PERMIT_ALL_ATTRIBUTE.equals(attribute)) {
			return ACCESS_GRANTED;
		}
		//@DenyAll 反對(duì)
		if (Jsr250SecurityConfig.DENY_ALL_ATTRIBUTE.equals(attribute)) {
			return ACCESS_DENIED;
		}
		//supports
		if (supports(attribute)) {
			jsr250AttributeFound = true;
			// 如果已授權(quán)則投贊成票
			for (GrantedAuthority authority : authentication.getAuthorities()) {
				if (attribute.getAttribute().equals(authority.getAuthority())) {
					return ACCESS_GRANTED;
				}
			}
		}
	}
	// 未授權(quán)但是support的投反對(duì)票,未support的棄權(quán)
	return jsr250AttributeFound ? ACCESS_DENIED : ACCESS_ABSTAIN;
}

以上就是Spring Security對(duì)授權(quán)功能的實(shí)現(xiàn),如果決斷的最終結(jié)果是通過(guò),則Filter會(huì)繼續(xù)執(zhí)行下去,否則會(huì)拋出異常。授權(quán)整體流程如下圖

SpringSecurity原理是什么

到此,相信大家對(duì)“SpringSecurity原理是什么”有了更深的了解,不妨來(lái)實(shí)際操作一番吧!這里是創(chuàng)新互聯(lián)網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!

網(wǎng)站題目:SpringSecurity原理是什么
文章起源:http://chinadenli.net/article20/gsheco.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供面包屑導(dǎo)航品牌網(wǎng)站設(shè)計(jì)自適應(yīng)網(wǎng)站Google品牌網(wǎng)站制作網(wǎng)站改版

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

外貿(mào)網(wǎng)站建設(shè)