結合開源軟件kaptcha講解登陸驗證碼功能的實現

file

1、驗證碼生成之配置使用kaptcha

使用google開源的驗證碼實現類庫kaptcha,經過maven座標引入前端

<dependency>
   <groupId>com.github.penggle</groupId>
   <artifactId>kaptcha</artifactId>
   <version>2.3.2</version>
   <exclusions>
      <exclusion>
         <artifactId>javax.servlet-api</artifactId>
         <groupId>javax.servlet</groupId>
      </exclusion>
   </exclusions>
</dependency>
  • 假設咱們的配置文件是application.yml,新建一個單獨的文件叫作kaptcha.properties。由於kaptcha的配置不符合yaml的規範格式,因此只能採用properties。需配合註解PropertySourc使用。
  • 假設咱們的配置文件是application.properties,將下面這段代碼加入進去便可,不用單獨創建文件。
  • 下面的驗證碼配置,從英文單詞的角度很容易理解,當咱們須要調整驗證碼的邊框、顏色、大小、字體等屬性的時候,能夠修改這些配置。
kaptcha.border=no
kaptcha.border.color=105,179,90
kaptcha.image.width=100
kaptcha.image.height=45
kaptcha.session.key=code
kaptcha.textproducer.font.color=blue
kaptcha.textproducer.font.size=35
kaptcha.textproducer.char.length=4
kaptcha.textproducer.font.names=宋體,楷體,微軟雅黑

下面的代碼加載了配置文件中的kaptcha配置(參考Spring Boot的配置加載),若是是獨立的properties文件,需加上PropertySource註解說明。
另外,咱們經過加載完成的配置,初始化captchaProducer的Spring Bean,用於生成驗證碼。java

@Component
@PropertySource(value = {"classpath:kaptcha.properties"})
public class CaptchaConfig {

    @Value("${kaptcha.border}")
    private String border;
    @Value("${kaptcha.border.color}")
    private String borderColor;
    @Value("${kaptcha.textproducer.font.color}")
    private String fontColor;
    @Value("${kaptcha.image.width}")
    private String imageWidth;
    @Value("${kaptcha.image.height}")
    private String imageHeight;
    @Value("${kaptcha.session.key}")
    private String sessionKey;
    @Value("${kaptcha.textproducer.char.length}")
    private String charLength;
    @Value("${kaptcha.textproducer.font.names}")
    private String fontNames;
    @Value("${kaptcha.textproducer.font.size}")
    private String fontSize;

    @Bean(name = "captchaProducer")
    public DefaultKaptcha getKaptchaBean() {
        DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
        Properties properties = new Properties();
        properties.setProperty("kaptcha.border", border);
        properties.setProperty("kaptcha.border.color", borderColor);
        properties.setProperty("kaptcha.textproducer.font.color", fontColor);
        properties.setProperty("kaptcha.image.width", imageWidth);
        properties.setProperty("kaptcha.image.height", imageHeight);
        properties.setProperty("kaptcha.session.key", sessionKey);
        properties.setProperty("kaptcha.textproducer.char.length", charLength);
        properties.setProperty("kaptcha.textproducer.font.names", fontNames);
        properties.setProperty("kaptcha.textproducer.font.size",fontSize);
        Config config = new Config(properties);
        defaultKaptcha.setConfig(config);
        return defaultKaptcha;
    }

}

至此,Kaptcha開源驗證碼軟件的配置咱們就完成了,若是發現IDEA環境下配置文件讀取中文亂碼,修改以下配置。
git

2、驗證碼生成之session保存

生成驗證碼的Controller。同時須要開放路徑"/kaptcha"的訪問權限,配置成不需登陸也無需任何權限便可訪問的路徑。如何進行配置,筆者以前的文章已經講過了。github

  • 經過captchaProducer.createText()生成驗證碼文字,並和失效時間一塊兒保存到CaptchaImageVO中。
  • 將CaptchaImageVO驗證碼信息類對象,保存到session中。(這個類的代碼後文有介紹)
  • 經過captchaProducer.createImage(capText)生成驗證碼圖片,並經過ServletOutputStream返回給前端
@RestController
public class CaptchaController {

    @Resource
    DefaultKaptcha captchaProducer;

    /**
     * 獲取驗證碼
     */
    @RequestMapping(value = "/kaptcha", method = RequestMethod.GET)
    public void kaptcha(HttpSession session, HttpServletResponse response) throws Exception {

        response.setDateHeader("Expires", 0);
        response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");
        response.addHeader("Cache-Control", "post-check=0, pre-check=0");
        response.setHeader("Pragma", "no-cache");
        response.setContentType("image/jpeg");

        String capText = captchaProducer.createText();
        CaptchaImageVO captchaImageVO = new CaptchaImageVO(capText,2 * 60);
        //將驗證碼存到session
        session.setAttribute(Constants.KAPTCHA_SESSION_KEY, captchaImageVO);

        //將圖片返回給前端
        try(ServletOutputStream out = response.getOutputStream();) {
            BufferedImage bi = captchaProducer.createImage(capText);
            ImageIO.write(bi, "jpg", out);
            out.flush();
        }//使用try-with-resources不用手動關閉流
    }

}

咱們要把CaptchaImageVO保存到session裏面。因此該類中不要加圖片,只保存驗證碼文字和失效時間,用於後續驗證便可。把驗證碼圖片保存起來既沒有用處,又浪費內存。spring

@Data
public class CaptchaImageVO {

    //驗證碼文字
    private String code;
    //驗證碼失效時間
    private LocalDateTime expireTime;
 
    public CaptchaImageVO(String code, int expireAfterSeconds){
        this.code = code;
        this.expireTime = LocalDateTime.now().plusSeconds(expireAfterSeconds);
    }
 
    //驗證碼是否失效
    public boolean isExpried() {
        return LocalDateTime.now().isAfter(expireTime);
    }
 
}

3、驗證碼用戶訪問

把以下代碼加入到登陸頁面合適的位置,注意圖片img標籤放到登陸表單中。api

<img src="/kaptcha" id="kaptcha" width="110px" height="40px"/>

<script>
    window.onload=function(){
        var kaptchaImg = document.getElementById("kaptcha");
        kaptchaImg.onclick = function(){
            kaptchaImg.src = "/kaptcha?" + Math.floor(Math.random() * 100)
        }
    }
</script>
  • 實現的效果是,頁面初始化即加載驗證碼。之後每一次點擊,都會更新驗證碼。
  • 注意:必定設置width和height,不然圖片沒法顯示。

4、驗證碼之安全校驗

  • 編寫咱們的自定義圖片驗證碼過濾器VerificationCodeFilter,過濾器中攔截登陸請求
  • VerificationCodeFilter過濾器中從seesion獲取驗證碼文字與用戶輸入比對,比對經過執行其餘過濾器鏈
  • 比對不經過,自定義一個異常,交給AuthenticationFailureHandler處理
  • 最後將VerificationCodeFilter放在UsernamePasswordAuthenticationFilter表單過濾器以前執行。

以上是在Spring Security實現登陸驗證碼驗證的邏輯。若是你是使用的shiro或者其餘的自定義的登陸驗證明現,那就更簡單了。就在你的登陸驗證的controller裏面取出session比對驗證碼便可,不須要自定義過濾器。安全

期待您的關注

相關文章
相關標籤/搜索