亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Spring Security登陸流程講解

 更新時(shí)間:2021年11月04日 14:01:13   作者:Java Gosling  
本文主要介紹了Spring Security登陸流程講解,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

在Spring Security中,認(rèn)證授權(quán)都是通過過濾器來實(shí)現(xiàn)的。

當(dāng)開始登陸的時(shí)候,有一個(gè)關(guān)鍵的過濾器UsernamePasswordAuthenticationFilter,該類繼承抽象類AbstractAuthenticationProcessingFilter,在AbstractAuthenticationProcessingFilter里有一個(gè)doFilter方法,一切先從這里說起。

private void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
      throws IOException, ServletException {
   if (!requiresAuthentication(request, response)) {
      chain.doFilter(request, response);
      return;
   }
   try {
      Authentication authenticationResult = attemptAuthentication(request, response);
      if (authenticationResult == null) {
         // return immediately as subclass has indicated that it hasn't completed
         return;
      }
      this.sessionStrategy.onAuthentication(authenticationResult, request, response);
      // Authentication success
      if (this.continueChainBeforeSuccessfulAuthentication) {
         chain.doFilter(request, response);
      }
      successfulAuthentication(request, response, chain, authenticationResult);
   }
   catch (InternalAuthenticationServiceException failed) {
      this.logger.error("An internal error occurred while trying to authenticate the user.", failed);
      unsuccessfulAuthentication(request, response, failed);
   }
   catch (AuthenticationException ex) {
      // Authentication failed
      unsuccessfulAuthentication(request, response, ex);
   }
}

首先requiresAuthentication先判斷是否嘗試校驗(yàn),通過后調(diào)用attemptAuthentication方法,這個(gè)方法也就是UsernamePasswordAuthenticationFilter 中的attemptAuthentication方法。

public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
      throws AuthenticationException {
   if (this.postOnly && !request.getMethod().equals("POST")) {
      throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
   }
   String username = obtainUsername(request);
   username = (username != null) ? username : "";
   username = username.trim();
   String password = obtainPassword(request);
   password = (password != null) ? password : "";
   UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);
   // Allow subclasses to set the "details" property
   setDetails(request, authRequest);
   return this.getAuthenticationManager().authenticate(authRequest);
}

1.在UsernamePasswordAuthenticationFilter 的attemptAuthentication方法中,先是驗(yàn)證請(qǐng)求的類型,是否是POST請(qǐng)求,如果不是的話,拋出異常。(PS:登陸肯定要用POST方法了)
2.然后拿到username和password。這里使用的是obtainUsername方法,也就是get方法。

@Nullable
protected String obtainPassword(HttpServletRequest request) {
   return request.getParameter(this.passwordParameter);
}

@Nullable
protected String obtainUsername(HttpServletRequest request) {
   return request.getParameter(this.usernameParameter);
}

由此我們知道了Spring Security中是通過get方法來拿到參數(shù),所以在進(jìn)行前后端分離的時(shí)候是無法接受JSON數(shù)據(jù),處理方法就是自定義一個(gè)Filter來繼承UsernamePasswordAuthenticationFilter,重寫attemptAuthentication方法,然后創(chuàng)建一個(gè)Filter實(shí)例寫好登陸成功和失敗的邏輯處理,在HttpSecurity參數(shù)的configure中通過addFilterAt來替換Spring Security官方提供的過濾器。
3.創(chuàng)建一個(gè)UsernamePasswordAuthenticationToken 實(shí)例。
4.設(shè)置Details,在這里關(guān)鍵的是在WebAuthenticationDetails類中記錄了用戶的remoteAddress和sessionId。

public WebAuthenticationDetails(HttpServletRequest request) {
   this.remoteAddress = request.getRemoteAddr();
   HttpSession session = request.getSession(false);
   this.sessionId = (session != null) ? session.getId() : null;
}

5.拿到一個(gè)AuthenticationManager通過authenticate方法進(jìn)行校驗(yàn),這里以實(shí)現(xiàn)類ProviderManager為例。

@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
   //獲取Authentication的運(yùn)行時(shí)類
   Class<? extends Authentication> toTest = authentication.getClass();
   AuthenticationException lastException = null;
   AuthenticationException parentException = null;
   Authentication result = null;
   Authentication parentResult = null;
   int currentPosition = 0;
   int size = this.providers.size();
   
   for (AuthenticationProvider provider : getProviders()) {
       //判斷是否支持處理該類別的provider
      if (!provider.supports(toTest)) {
         continue;
      }
      if (logger.isTraceEnabled()) {
         logger.trace(LogMessage.format("Authenticating request with %s (%d/%d)",
               provider.getClass().getSimpleName(), ++currentPosition, size));
      }
      try {
          //獲取用戶的信息
         result = provider.authenticate(authentication);
         if (result != null) {
            copyDetails(authentication, result);
            break;
         }
      }
      catch (AccountStatusException | InternalAuthenticationServiceException ex) {
         prepareException(ex, authentication);
         // SEC-546: Avoid polling additional providers if auth failure is due to
         // invalid account status
         throw ex;
      }
      catch (AuthenticationException ex) {
         lastException = ex;
      }
   }
   //不支持的話跳出循環(huán)再次執(zhí)行
   if (result == null && this.parent != null) {
      // Allow the parent to try.
      try {
         parentResult = this.parent.authenticate(authentication);
         result = parentResult;
      }
      catch (ProviderNotFoundException ex) {
         // ignore as we will throw below if no other exception occurred prior to
         // calling parent and the parent
         // may throw ProviderNotFound even though a provider in the child already
         // handled the request
      }
      catch (AuthenticationException ex) {
         parentException = ex;
         lastException = ex;
      }
   }
   if (result != null) {
       //擦除用戶的憑證 也就是密碼
      if (this.eraseCredentialsAfterAuthentication && (result instanceof CredentialsContainer)) {
         // Authentication is complete. Remove credentials and other secret data
         // from authentication
         ((CredentialsContainer) result).eraseCredentials();
      }
      // If the parent AuthenticationManager was attempted and successful then it
      // will publish an AuthenticationSuccessEvent
      // This check prevents a duplicate AuthenticationSuccessEvent if the parent
      // AuthenticationManager already published it
      if (parentResult == null) {
          //公示登陸成功
         this.eventPublisher.publishAuthenticationSuccess(result);
      }

      return result;
   }

   // Parent was null, or didn't authenticate (or throw an exception).
   if (lastException == null) {
      lastException = new ProviderNotFoundException(this.messages.getMessage("ProviderManager.providerNotFound",
            new Object[] { toTest.getName() }, "No AuthenticationProvider found for {0}"));
   }
   // If the parent AuthenticationManager was attempted and failed then it will
   // publish an AbstractAuthenticationFailureEvent
   // This check prevents a duplicate AbstractAuthenticationFailureEvent if the
   // parent AuthenticationManager already published it
   if (parentException == null) {
      prepareException(lastException, authentication);
   }
   throw lastException;
}

 6.經(jīng)過一系列校驗(yàn),此時(shí)登陸校驗(yàn)基本完成,當(dāng)驗(yàn)證通過后會(huì)執(zhí)行doFilter中的successfulAuthentication方法,跳轉(zhuǎn)到我們?cè)O(shè)置的登陸成功界面,驗(yàn)證失敗會(huì)執(zhí)行unsuccessfulAuthentication方法,跳轉(zhuǎn)到我們?cè)O(shè)置的登陸失敗界面。

到此這篇關(guān)于Spring Security登陸流程講解的文章就介紹到這了,更多相關(guān)Spring Security登陸內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringCloud Eureka服務(wù)的基本配置和操作方法

    SpringCloud Eureka服務(wù)的基本配置和操作方法

    Eureka是Netflix開源的一個(gè)基于REST的服務(wù)治理框架,主要用于實(shí)現(xiàn)微服務(wù)架構(gòu)中的服務(wù)注冊(cè)與發(fā)現(xiàn),Eureka是Netflix開源的服務(wù)發(fā)現(xiàn)框架,用于在分布式系統(tǒng)中實(shí)現(xiàn)服務(wù)的自動(dòng)注冊(cè)與發(fā)現(xiàn),本文介紹SpringCloud Eureka服務(wù)的基本配置和操作方法,感興趣的朋友一起看看吧
    2023-12-12
  • mybatis自動(dòng)填充時(shí)間字段示例代碼

    mybatis自動(dòng)填充時(shí)間字段示例代碼

    這篇文章主要給大家介紹了關(guān)于mybatis自動(dòng)填充時(shí)間字段的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-01-01
  • 最全MyBatis核心配置文件總結(jié)(收藏)

    最全MyBatis核心配置文件總結(jié)(收藏)

    這篇文章主要介紹了最全MyBatis核心配置文件總結(jié)(收藏),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-11-11
  • SpringBoot入門教程詳解

    SpringBoot入門教程詳解

    SpringBoot?是由?Pivotal?團(tuán)隊(duì)提供的全新框架,其設(shè)計(jì)目的是用來簡(jiǎn)化?Spring?應(yīng)用的初始搭建以及開發(fā)過程。本文將詳細(xì)為大家講講SpringBoot是使用,需要的可以參考一下
    2022-06-06
  • Spring事務(wù)處理原理步驟詳解

    Spring事務(wù)處理原理步驟詳解

    這篇文章主要介紹了Spring事務(wù)處理原理步驟詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-03-03
  • Spring Boot 之HelloWorld開發(fā)案例

    Spring Boot 之HelloWorld開發(fā)案例

    這篇文章主要介紹了Spring Boot 之HelloWorld開發(fā)案例,需要的朋友可以參考下
    2017-04-04
  • SpringMVC靜態(tài)資源配置過程詳解

    SpringMVC靜態(tài)資源配置過程詳解

    在javaweb項(xiàng)目中配置了DispatcherServlet的情況下,如果不進(jìn)行額外配置的話,幾乎所有的請(qǐng)求都會(huì)走這個(gè)servlet來處理,默認(rèn)靜態(tài)資源按路徑是訪問不到的會(huì)報(bào)404錯(cuò)誤,下面就來講一講如何配置才能訪問到靜態(tài)資源吧
    2022-08-08
  • java 使用foreach遍歷集合元素的實(shí)例

    java 使用foreach遍歷集合元素的實(shí)例

    這篇文章主要介紹了java 使用foreach遍歷集合元素的實(shí)例的相關(guān)資料,這里提供實(shí)例幫助大家理解如何使用foreach 進(jìn)行遍歷,希望能幫助到大家,
    2017-08-08
  • 淺談Spring Cloud Eureka 自我保護(hù)機(jī)制

    淺談Spring Cloud Eureka 自我保護(hù)機(jī)制

    這篇文章主要介紹了淺談Spring Cloud Eureka 自我保護(hù)機(jī)制,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-06-06
  • 詳解RocketMQ 消費(fèi)端如何監(jiān)聽消息

    詳解RocketMQ 消費(fèi)端如何監(jiān)聽消息

    這篇文章主要為大家介紹了RocketMQ 消費(fèi)端如何監(jiān)聽消息示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-12-12

最新評(píng)論