一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - Spring Security基于過濾器實現圖形驗證碼功能

Spring Security基于過濾器實現圖形驗證碼功能

2022-01-19 00:58一一哥Sun Java教程

驗證碼就是為了防止惡意用戶采用暴力重試的攻擊手段而設置的一種防護措施,接下來在Spring Security的環境中,我們可以用兩種方案實現圖形驗證碼,具體實現方法跟隨小編一起看看吧

前言

在前兩個章節中,一一哥 帶大家學習了Spring Security內部關于認證授權的核心API,以及認證授權的執行流程和底層原理。掌握了這些之后,對于Spring Security,我們不僅做到了 "知其然",而且也做到了 "知其所以然"

在現在的求職環境下,只知道某個技能點的用法是遠遠不夠的,面試官會要求我們研究某個技術的底層實現原理,所以雖然前面的兩章內容掌握起來很有難度,但是還是希望各位小伙伴結合源碼認真研讀,這樣你才能在編程之路上走的更遠更高!

總是研究底層,對于我們初學者來說,既有難度,也會影響咱們的學習積極性,所以從本篇文章開始,咱們繼續學習Spring Security的其他用法,比如我們學習一下如何在Spring Security中添加執行自定義的過濾器,進而實現驗證碼校驗功能。

 

一. 驗證碼簡介

在進行驗證碼編碼實現之前,壹哥 先給各位介紹一下驗證碼的概念和作用。

驗證碼(CAPTCHA):全稱是Completely Automated Public Turing test to tell Computers and Humans Apart,翻譯過來就是“全自動區分計算機和人類的圖靈測試”。通俗的講,驗證碼就是為了防止惡意用戶采用暴力重試的攻擊手段而設置的一種防護措施。我們在進行用戶注冊、登錄、或者論壇發帖時都可以利用驗證碼,對某些惡意用戶利用計算機發起無限重試進行必要的攔截限制。

接下來在Spring Security的環境中,我們可以用如下兩種方案實現圖形驗證碼:

  • 基于自定義的過濾器來實現圖形驗證碼;
  • 基于自定義的認證器來實現圖形驗證碼。

在本篇文章中,壹哥 先利用第一種方案,也就是基于自定義的過濾器的方式,來教會大家如何實現圖形驗證碼,請繼續往下看哦。

 

二. 基于過濾器實現圖形驗證碼

1. 實現概述

在Spring Security中,實現驗證碼校驗的方式有很多種,其中基于過濾器來實現圖形驗證碼是最簡單的方式。小伙伴可能會問,過濾器如何實現驗證碼校驗功能呢?基于什么原理?這個其實很簡單,流程原理就是我們先自定義一個過濾器Filter,處理驗證碼的驗證邏輯,然后把該過濾器添加到Spring Security過濾器鏈的某個合適位置。當匹配到登錄請求時,過濾器會對驗證碼進行校驗,如果成功則放行,如果失敗則結束當前驗證請求。

明白了實現流程和原理后,接下來我們就在之前項目的基礎之上,進行驗證碼功能的代碼實現。

2. 創建新模塊

我們可以創建一個新的項目model,創建過程與之前一樣,這里就略過了。

3. 添加依賴包

本案例中,我們采用github上的開源驗證碼解決方案kaptcha,所以需要在原有項目的基礎上添加kaptcha的依賴包。

<dependencies>
      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-web</artifactId>
      </dependency>

      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-security</artifactId>
      </dependency>

      <dependency>
          <groupId>org.mybatis.spring.boot</groupId>
          <artifactId>mybatis-spring-boot-starter</artifactId>
          <version>1.3.1</version>
      </dependency

      <dependency>
          <groupId>mysql</groupId>
          <artifactId>mysql-connector-java</artifactId>
          <scope>runtime</scope>
      </dependency>

      <dependency>
          <groupId>com.github.penggle</groupId>
          <artifactId>kaptcha</artifactId>
          <version>2.3.2</version>
      </dependency>

      <dependency>
          <groupId>org.springframework.security</groupId>
          <artifactId>spring-security-test</artifactId>
          <scope>test</scope>
      </dependency>
  </dependencies>

4. 創建Producer對象

在準備好依賴包之后,接下來我們創建一個CaptchaConfig配置類,在該類中創建一個Producer對象,對驗證碼對象進行必要的配置,比如設置驗證碼背景框的寬度和高度,驗證碼的字符集,驗證碼的個數等。

@Configuration
public class CaptchaConfig {

  @Bean
  public Producer captcha() {
      // 配置圖形驗證碼的基本參數
      Properties properties = new Properties();
      // 圖片寬度
      properties.setProperty("kaptcha.image.wth", "150");
      // 圖片長度
      properties.setProperty("kaptcha.image.height", "50");
      // 字符集
      properties.setProperty("kaptcha.textproducer.char.string", "0123456789");
      // 字符長度
      properties.setProperty("kaptcha.textproducer.char.length", "4");
      Config config = new Config(properties);
      // 使用默認的圖形驗證碼實現,當然也可以自定義實現
      DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
      defaultKaptcha.setConfig(config);
      return defaultKaptcha;
  }

}

5. 創建生成驗證碼的接口

在上面創建了Producer對象后,接著我們再創建一個生成驗證碼的接口,該接口中負責生成驗證碼圖片,并且記得要把生成的驗證碼存放到session中,以便后面發起登錄請求時進行比對驗證碼。

@Controller
public class CaptchaController {

  @Autowired
  private Producer captchaProducer;

  @GetMapping("/captcha.jpg")
  public vo getCaptcha(HttpServletRequest request, HttpServletResponse response) throws IOException {
      // 設置內容類型
      response.setContentType("image/jpeg");
      // 創建驗證碼文本
      String capText = captchaProducer.createText();
      
      // 將驗證碼文本設置到session
      request.getSession().setAttribute("captcha", capText);
      
      // 創建驗證碼圖片
      BufferedImage bi = captchaProducer.createImage(capText);
      // 獲取響應輸出流
      ServletOutputStream out = response.getOutputStream();
      // 將圖片驗證碼數據寫到響應輸出流
      ImageIO.write(bi, "jpg", out);
      
      // 推送并關閉響應輸出流
      try {
          out.flush();
      } finally {
          out.close();
      }
  }

}

6. 自定義異常

我們可以自定義一個運行時異常,用于處理驗證碼校驗失敗時拋出異常提示信息,當然這個并不是必須的。

public class VerificationCodeException extends AuthenticationException {

  public VerificationCodeException () {
      super("圖形驗證碼校驗失敗");
  }

}

7. 創建攔截驗證碼的過濾器

創建驗證碼并保存到session之后,另一個很重要的工作就是比對用戶從前端傳遞過來的驗證碼是否相同,這個比對工作我們就在自定義的過濾器中進行實現。所以接著我們就創建一個過濾器,負責對用戶發來的驗證碼進行攔截校驗,看看request請求中傳遞過來的驗證碼,與我們生成并保存在session中的驗證碼是否一致。

/**
* 基于過濾器實現圖形驗證碼的驗證功能,這屬于Servlet層面,簡單易理解.
*/
public class VerificationCodeFilter extends OncePerRequestFilter {

  private AuthenticationFailureHandler authenticationFailureHandler = new SecurityAuthenticationFailureHandler();

  @Overre
  protected vo doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
      // 非登錄請求不校驗驗證碼,直接放行
      if (!"/login".equals(httpServletRequest.getRequestURI())) {
          filterChain.doFilter(httpServletRequest, httpServletResponse);
      } else {
          try {
              //校驗驗證碼
              verificationCode(httpServletRequest);
              
              //驗證碼校驗通過后,對請求進行放行
              filterChain.doFilter(httpServletRequest, httpServletResponse);
          } catch (VerificationCodeException e) {
              authenticationFailureHandler.onAuthenticationFailure(httpServletRequest, httpServletResponse, e);
          }
      }
  }

  public vo verificationCode (HttpServletRequest httpServletRequest) throws VerificationCodeException {
      HttpSession session = httpServletRequest.getSession();
      String savedCode = (String) session.getAttribute("captcha");
      if (!StringUtils.isEmpty(savedCode)) {
          // 隨手清除驗證碼,不管是失敗還是成功,所以客戶端應在登錄失敗時刷新驗證碼
          session.removeAttribute("captcha");
      }

      String requestCode = httpServletRequest.getParameter("captcha");
      // 校驗不通過拋出異常
      if (StringUtils.isEmpty(requestCode) || StringUtils.isEmpty(savedCode) || !requestCode.equals(savedCode)) {
          throw new VerificationCodeException();
      }
  }

}

8. 編寫SecurityConfig

接下來我們需要編寫一個SecurityConfig配置類,在該配置類中,把咱們前面編寫的驗證碼過濾器添加在默認的UsernamePasswordAuthenticationFilter過濾器之前來執行,可以利用http.addFilterBefore()方法來實現。

對于UsernamePasswordAuthenticationFilter過濾器,你還能想起來嗎?如果想不起來,請看我前一篇文章,里面有詳細講解哦!

/**
* @Author: 一一哥
* 增加圖形驗證碼功能.
*/
@EnableWebSecurity(debug = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

  @Overre
  protected vo configure(HttpSecurity http) throws Exception {
      http.authorizeRequests()
              .antMatchers("/admin/api/**")
              .hasRole("ADMIN")
              .antMatchers("/user/api/**")
              .hasRole("USER")
              .antMatchers("/app/api/**", "/captcha.jpg")
              .permitAll()
              .anyRequest()
              .authenticated()
              .and()
              .formLogin()
              .failureHandler(new SecurityAuthenticationFailureHandler())
              .successHandler(new SecurityAuthenticationSuccessHandler())
              .loginPage("/myLogin.html")
              .loginProcessingUrl("/login")
              .permitAll()
              .and()
              .csrf()
              .disable();

      //將過濾器添加在UsernamePasswordAuthenticationFilter之前
      http.addFilterBefore(new VerificationCodeFilter(), UsernamePasswordAuthenticationFilter.class);
  }

  @Bean
  public PasswordEncoder passwordEncoder() {
      return NoOpPasswordEncoder.getInstance();
  }

}

在這里,我們把自定義的驗證碼校驗過濾器VerificationCodeFilter,添加到了Spring Security自帶的UsernamePasswordAuthenticationFilter過濾器前面。

注:

關于我們測試的web接口,數據庫配置、認證成功、失敗時的Handler處理器等,請參考前面《基于Spring Security前后端分離的權限控制系統問題》案例,此處略過。

9. 編寫測試頁面

既然要實現驗證碼功能,為了方便測試,我們需要編寫一個自定義的登錄頁面,并在這里添加對驗證碼接口的引用,這里列出html頁面的核心代碼。

<body>
  <div class="login">
      <h2>Access Form</h2>
      <div class="login-top">
          <h1>登錄驗證</h1>
          <form action="/login" method="post">
               <input type="text" name="username" placeholder="username" />
               <input type="password" name="password" placeholder="password" />
               <div style="display: flex;">
                   <!-- 新增圖形驗證碼的輸入框 -->
                   <input type="text" name="captcha" placeholder="captcha" />
                   <!-- 圖片指向圖形驗證碼API -->
                   <img src="/captcha.jpg"               </div>
               <div class="forgot">
                   <a href="#">忘記密碼</a>
                   <input type="submit" value="登錄" >
               </div>
          </form>
     </div>
     <div class="login-bottom">
         <h3>新用戶&nbsp;<a href="#">注&nbsp;冊</a></h3>
     </div>
 </div>
</body>

10. 代碼結構

整個項目的代碼結構如下,請參考下圖進行實現。

Spring Security基于過濾器實現圖形驗證碼功能

11. 啟動項目測試

接下來我們啟動項目,在訪問受限接口時,會重定向到myLogin.html登錄頁面,可以看到我們的驗證碼效果已經顯示出來了。

Spring Security基于過濾器實現圖形驗證碼功能

接下來我們輸入正確的用戶名、密碼、驗證碼后,就可以成功的登錄進去訪問web接口了。

至此,基于自定義過濾器實現的驗證碼功能,壹哥 就帶各位實現完畢,你學會了嗎?如有疑問,可以在評論區留言。

到此這篇關于Spring Security基于過濾器實現圖形驗證碼功能的文章就介紹到這了,更多相關Spring Security圖形驗證碼內容請搜索服務器之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持服務器之家!

原文鏈接:https://blog.csdn.net/syc000666/article/details/120481479

延伸 · 閱讀

精彩推薦
  • Java教程小米推送Java代碼

    小米推送Java代碼

    今天小編就為大家分享一篇關于小米推送Java代碼,小編覺得內容挺不錯的,現在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧...

    富貴穩中求8032021-07-12
  • Java教程Java實現搶紅包功能

    Java實現搶紅包功能

    這篇文章主要為大家詳細介紹了Java實現搶紅包功能,采用多線程模擬多人同時搶紅包,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙...

    littleschemer13532021-05-16
  • Java教程升級IDEA后Lombok不能使用的解決方法

    升級IDEA后Lombok不能使用的解決方法

    最近看到提示IDEA提示升級,尋思已經有好久沒有升過級了。升級完畢重啟之后,突然發現好多錯誤,本文就來介紹一下如何解決,感興趣的可以了解一下...

    程序猿DD9332021-10-08
  • Java教程Java使用SAX解析xml的示例

    Java使用SAX解析xml的示例

    這篇文章主要介紹了Java使用SAX解析xml的示例,幫助大家更好的理解和學習使用Java,感興趣的朋友可以了解下...

    大行者10067412021-08-30
  • Java教程xml與Java對象的轉換詳解

    xml與Java對象的轉換詳解

    這篇文章主要介紹了xml與Java對象的轉換詳解的相關資料,需要的朋友可以參考下...

    Java教程網2942020-09-17
  • Java教程Java BufferWriter寫文件寫不進去或缺失數據的解決

    Java BufferWriter寫文件寫不進去或缺失數據的解決

    這篇文章主要介紹了Java BufferWriter寫文件寫不進去或缺失數據的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望...

    spcoder14552021-10-18
  • Java教程20個非常實用的Java程序代碼片段

    20個非常實用的Java程序代碼片段

    這篇文章主要為大家分享了20個非常實用的Java程序片段,對java開發項目有所幫助,感興趣的小伙伴們可以參考一下 ...

    lijiao5352020-04-06
  • Java教程Java8中Stream使用的一個注意事項

    Java8中Stream使用的一個注意事項

    最近在工作中發現了對于集合操作轉換的神器,java8新特性 stream,但在使用中遇到了一個非常重要的注意點,所以這篇文章主要給大家介紹了關于Java8中S...

    阿杜7482021-02-04
主站蜘蛛池模板: 高清一区高清二区视频 | 欧美亚洲国产精品久久久 | 韩国办公室激情 | 精品一区二区三区免费视频 | 99自拍视频在线观看 | 双性少爷受糙汉攻h | 国产日韩欧美在线观看不卡 | 欧美a欧美1级 | 四虎网址大全 | 男人午夜视频在线观看 | 小sao货水好多真紧h的视频 | 免费在线观看网址大全 | 激情另类国内一区二区视频 | 日韩欧美色图 | 国内精品91东航翘臀女神在线 | 秋霞一级| 日本一区二区三区国产 | 欧美成人免费观看久久 | 调教女高中生第3部分 | 日韩一级片在线播放 | 99爱在线观看 | 亚洲精品第五页中文字幕 | 91日本在线观看亚洲精品 | 亚洲日本aⅴ片在线观看香蕉 | a级亚洲片精品久久久久久久 | 色天使亚洲综合在线观看 | 国产男女乱淫真视频全程播放 | 成人日批视频 | 日韩免费高清专区 | 99久久综合精品免费 | 91果冻制片厂天美传媒 | 国产好痛疼轻点好爽的视频 | 天天操天天爽天天射 | 菠萝视频在线完整版 | 美女脱了内裤打开腿让男人图片 | 亚洲精品久久久久AV无码 | yellow高清视频日本动漫 | 色播艾小青国产专区在线播放 | 国产精品四虎在线观看免费 | 久久99国产亚洲高清观着 | 午夜人妻理论片天堂影院 |