溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

SpringSecurity原理是什么

發(fā)布時(shí)間:2021-10-26 10:05:31 來源:億速云 閱讀:262 作者:iii 欄目:編程語言

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

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

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

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

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

身份認(rèn)證

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

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

身份識別令牌

一個(gè)完整的身份識別令牌應(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();
    // 主體:【賬號】  
    Object getPrincipal();
    // 是否已認(rèn)證:true為已認(rèn)證
    boolean isAuthenticated();
    // 設(shè)置是否已認(rèn)證:
    void setAuthenticated(boolean var1) throws IllegalArgumentException;
}

客戶端不能提供完整的身份識別令牌,因?yàn)榭蛻舳说男畔⒉⒉豢煽?,因此一般而言客戶端不需要提供完整的令牌信息,只需要提供能識別出所屬人Principal的識別碼即可,剩余的信息交給服務(wù)端去填充。Spring Security的身份認(rèn)證過程就是對身份識別令牌的填充過程。

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

以賬號密碼令牌為例

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

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

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

Authentication authResult = attemptAuthentication(request, response);

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

public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
	// 請求中獲取參數(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);
}

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

ProviderManager

AuthenticationManager是一個(gè)接口規(guī)范,其實(shí)現(xiàn)類為:ProviderManager,提供者管理器:管理能提供身份檔案信息的對象(AuthenticationProvider),能證明令牌確確實(shí)是屬于某個(gè)身份,能證明的方式有很多,Spring Security不是多方驗(yàn)證,而是首次驗(yàn)證成功即可,也就是說雖然有很多方式能證明令牌真的屬于誰,但是Spring Security只需要一個(gè)能提供證明身份證明的檔案即可。ProviderManager是一個(gè)父子分層結(jié)構(gòu),如果都不能證明則會去父管理器中去證明。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)證功能,針對特定令牌提供supports功能,而且基于職責(zé)單一原則,每種Token都會有一個(gè)AuthenticationProvider實(shí)現(xiàn)。

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

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

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

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

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

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

獲取到UserDetails就可以去認(rè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);
	// 前置賬號檢測:是否上鎖:LockedException,是否禁用:DisabledException,是否失效:AccountExpiredException
	preAuthenticationChecks.check(user);
	// 主體檢測:抽象方法:默認(rèn)為密碼匹配檢測
	additionalAuthenticationChecks(user,(UsernamePasswordAuthenticationToken) authentication);
	// 后置憑證檢測:憑證是否失效:CredentialsExpiredException
	postAuthenticationChecks.check(user);
    // 返回填充完整的令牌
    return createSuccessAuthentication(principalToReturn, authentication, user);
}

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

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

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

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

SpringSecurity原理是什么

身份授權(quán)

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

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

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

  • WebExpressionConfigAttribute


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

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


  • SecurityConfig


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

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


  • PreInvocationExpressionAttribute


    基于AOP前置通知表達(dá)式的訪問規(guī)則,主要是對@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á)式的訪問規(guī)則,主要是對@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ì)的安全訪問規(guī)則來源有好幾種,不同的安全訪問規(guī)則需要不同的處理機(jī)制來解析。能對某種安全訪問規(guī)則做出當(dāng)前請求能否通過該規(guī)則并訪問到資源的決斷的對象在Spring Security中抽象為AccessDecisionVoter:選民,做出決斷的動作稱為:vote:投票。AccessDecisionVoter只能對支持的安全訪問規(guī)則做出贊成、反對、棄權(quán)之一的決斷,每個(gè)決斷1個(gè)權(quán)重。接口規(guī)范如下:

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

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

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

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

Spring Security中對安全訪問規(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)為:一票通過方針:AffirmativeBased

決策方針

AffirmativeBased【一票通過方針】
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ù)同意,決策無效
	if (deny > grant) {
		throw new AccessDeniedException(messages.getMessage("AbstractAccessDecisionManager.accessDenied", "Access is denied"));
	}
	// 票數(shù)相等則根據(jù)allowIfEqualGrantedDeniedDecisions來決定是否通過
	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í)行需要選民參與投票,三大決策都是通過遍歷decisionVoters來統(tǒng)計(jì)vote結(jié)果的。不同的decisionVoter解析不同的安全訪問規(guī)則,因此當(dāng)一個(gè)訪問規(guī)則需要決斷時(shí),只有支持當(dāng)前訪問規(guī)則的decisionVoter才能做出決斷。因此需要知道一個(gè)訪問規(guī)則會被哪種decisionVoter解析

基于角色的選民【RoleVoter】

針對具有角色權(quán)限標(biāo)識的安全訪問規(guī)則進(jìn)行投票,角色權(quán)限標(biāo)識特征:private String rolePrefix = "ROLE_";,在Spring Security中角色權(quán)限都是該字符前綴,當(dāng)對用戶是否擁有該角色權(quán)限時(shí),就需要通過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);
	// 先判斷選民是否支持對該屬性進(jìn)行投票
	for (ConfigAttribute attribute : attributes) {
		if (this.supports(attribute)) {
			result = ACCESS_DENIED;
			// 當(dāng)支持時(shí),則從已授權(quán)集合中獲取到該權(quán)限標(biāo)識,如果獲取不到則表示無權(quán)限,投反對票
			// 已授權(quán)集合在身份認(rèn)證時(shí)已獲取
			for (GrantedAuthority authority : authorities) {
				if (attribute.getAttribute().equals(authority.getAuthority())) {
					return ACCESS_GRANTED;
				}
			}
		}
	}
	return result;
}
基于角色分級的選民【RoleHierarchyVoter】

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

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

分割方法

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

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

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

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

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

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

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

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

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

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

// 只支持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á)式只針對方法級別的@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】

針對Jsr250規(guī)范的注解@PermitAll和@DenyAll控制的權(quán)限,前置投贊成票,后置投反對票。對于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 反對
		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的投反對票,未support的棄權(quán)
	return jsr250AttributeFound ? ACCESS_DENIED : ACCESS_ABSTAIN;
}

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

SpringSecurity原理是什么

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

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI