本篇內(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ù)。
在上篇文章中提到構(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)證就是辨別出當(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。
一個(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)換令牌)等
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)一管理入口。
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作為一個(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)、密碼來(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)證信息齊全。
身份識(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)證流程圖示如下:
身份認(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ī)則,主要存在以下類型
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)); }
為了便于開發(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
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; ... } }
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")); } } ... }
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解析
針對(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; }
在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+");
針對(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í)投贊成票
針對(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); }
同樣是基于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; }
針對(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)整體流程如下圖
到此,相信大家對(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)