首頁  >  文章  >  Java  >  SpringBoot+kaptcha怎麼實作驗證碼

SpringBoot+kaptcha怎麼實作驗證碼

WBOY
WBOY轉載
2023-05-25 14:25:221548瀏覽

1. 基本用法

kaptcha 是個很老牌的驗證碼產生工具,多老呢?可以追溯到 2006 年。

這麼多年過去了,它不但沒有落寞反而還在被不少人使用,足以說明它的生命力了,值得我們來研究下。

方便起見,我們整一個 Spring Boot 工程來示範它的用法。

先新建一個Spring Boot 工程,然後加入kaptcha 的依賴,如下:

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

接下來我們只需要提供一個配置Kaptcha 的Bean 即可,如下:

@Configuration
public class KaptchaConfig {
    @Bean(name = "captchaProducer")
    public DefaultKaptcha getKaptchaBean() {
        DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
        Properties properties = new Properties();
        // 是否有边框 默认为true 我们可以自己设置yes,no
        properties.setProperty(KAPTCHA_BORDER, "yes");
        // 验证码文本字符颜色 默认为Color.BLACK
        properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_COLOR, "black");
        // 验证码图片宽度 默认为200
        properties.setProperty(KAPTCHA_IMAGE_WIDTH, "160");
        // 验证码图片高度 默认为50
        properties.setProperty(KAPTCHA_IMAGE_HEIGHT, "60");
        // 验证码文本字符大小 默认为40
        properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_SIZE, "38");
        // KAPTCHA_SESSION_KEY
        properties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, "kaptchaCode");
        // 验证码文本字符长度 默认为5
        properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "4");
        // 验证码文本字体样式 默认为new Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize)
        properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_NAMES, "Arial,Courier");
        // 图片样式 水纹com.google.code.kaptcha.impl.WaterRipple 鱼眼com.google.code.kaptcha.impl.FishEyeGimpy 阴影com.google.code.kaptcha.impl.ShadowGimpy
        properties.setProperty(KAPTCHA_OBSCURIFICATOR_IMPL, "com.google.code.kaptcha.impl.ShadowGimpy");
        Config config = new Config(properties);
        defaultKaptcha.setConfig(config);
        return defaultKaptcha;
    }
}

DefaultKaptcha 中配置驗證碼圖片的各個屬性值。各個屬性的意義,程式碼中都有註釋,我就不再多說了。

接下來我們在介面中回傳驗證碼圖片,如下:

@Autowired
DefaultKaptcha defaultKaptcha;
@GetMapping("/img")
public void getKaptcha(HttpServletResponse resp) throws IOException {
    String text = defaultKaptcha.createText();
    BufferedImage image = defaultKaptcha.createImage(text);
    ImageIO.write(image, "jpg", resp.getOutputStream());
}

我這裡是透過IO 流的形式將圖片寫到前端的,當然也可以將之轉為一個Base64字串回到前端,一樣也是OK 的。

等等,似乎少了什麼!

我們沒有把產生的驗證碼文字存入到 session 中去,這樣一會登入的時候沒法驗證,有小夥伴可能會說,這還不簡單?介面裡邊存一下不就行了?

NONONO!

大家看,當我們配置DefaultKaptcha bean 的時候,其中有這麼一行程式碼 properties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, "kaptchaCode");,這行程式碼的意思就是說會自動將產生的驗證碼文字存入到session 中,而session 的KEY 是kaptchaCode。但在實際測試中,大家會發現上面的程式碼不會將驗證碼產生的文字存入 session 中。

原因在於Kaptcha 工具其實自己提供了一個產生驗證碼圖片的Servlet,如果我們直接使用它自己提供的驗證碼Servlet,那麼上面這個設定才會生效,在Spring Boot 中,如果想要設定Kaptcha 自己提供的Servlet,方法如下:

@Bean
ServletRegistrationBean<HttpServlet> kaptchaServlet() {
    ServletRegistrationBean<HttpServlet> bean = new ServletRegistrationBean<>();
    bean.setServlet(new KaptchaServlet());
    bean.addUrlMappings("/img");
    Properties properties = new Properties();
    // 是否有边框 默认为true 我们可以自己设置yes,no
    properties.setProperty(KAPTCHA_BORDER, "yes");
    // 验证码文本字符颜色 默认为Color.BLACK
    properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_COLOR, "black");
    // 验证码图片宽度 默认为200
    properties.setProperty(KAPTCHA_IMAGE_WIDTH, "160");
    // 验证码图片高度 默认为50
    properties.setProperty(KAPTCHA_IMAGE_HEIGHT, "60");
    // 验证码文本字符大小 默认为40
    properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_SIZE, "38");
    // KAPTCHA_SESSION_KEY
    properties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, "kaptchaCode");
    // 验证码文本字符长度 默认为5
    properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "4");
    // 验证码文本字体样式 默认为new Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize)
    properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_NAMES, "Arial,Courier");
    // 图片样式 水纹com.google.code.kaptcha.impl.WaterRipple 鱼眼com.google.code.kaptcha.impl.FishEyeGimpy 阴影com.google.code.kaptcha.impl.ShadowGimpy
    properties.setProperty(KAPTCHA_OBSCURIFICATOR_IMPL, "com.google.code.kaptcha.impl.ShadowGimpy");
    Map<String, String> map = new HashMap<String,String>((Map)properties);
    bean.setInitParameters(map);
    return bean;
}

專案啟動後,直接存取 /img 就能看到驗證碼圖片,此時驗證碼的文字也會自動儲存入到session 中。當使用者登入的時候,透過 session.getAttribute("kaptchaCode") 就可以取得驗證碼的文字內容。

然而很多時候,驗證碼介面回傳的內容都是比較豐富的,可能不只是圖片,還有其他資訊。所以我們直接配一個Servlet 並不能滿足我們的要求,只能自己寫驗證碼的接口,自己寫的話,就要自己把驗證碼圖片存到session 中去,那麼 properties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, " kaptchaCode"); 配置其實就沒用了,可以不用加。

2. 自訂驗證碼文字

當然,我們也可以自訂驗證碼文本,只需要提供一個驗證碼文本的實作類別即可,如下:

public class KaptchaTextCreator extends DefaultTextCreator {
    private static final String[] CNUMBERS = "0,1,2,3,4,5,6,7,8,9,10".split(",");

    @Override
    public String getText() {
        Integer result = 0;
        Random random = new Random();
        int x = random.nextInt(10);
        int y = random.nextInt(10);
        StringBuilder suChinese = new StringBuilder();
        int randomoperands = (int) Math.round(Math.random() * 2);
        if (randomoperands == 0) {
            result = x * y;
            suChinese.append(CNUMBERS[x]);
            suChinese.append("*");
            suChinese.append(CNUMBERS[y]);
        } else if (randomoperands == 1) {
            if (!(x == 0) && y % x == 0) {
                result = y / x;
                suChinese.append(CNUMBERS[y]);
                suChinese.append("/");
                suChinese.append(CNUMBERS[x]);
            } else {
                result = x + y;
                suChinese.append(CNUMBERS[x]);
                suChinese.append("+");
                suChinese.append(CNUMBERS[y]);
            }
        } else if (randomoperands == 2) {
            if (x >= y) {
                result = x - y;
                suChinese.append(CNUMBERS[x]);
                suChinese.append("-");
                suChinese.append(CNUMBERS[y]);
            } else {
                result = y - x;
                suChinese.append(CNUMBERS[y]);
                suChinese.append("-");
                suChinese.append(CNUMBERS[x]);
            }
        } else {
            result = x + y;
            suChinese.append(CNUMBERS[x]);
            suChinese.append("+");
            suChinese.append(CNUMBERS[y]);
        }
        suChinese.append("=?@" + result);
        return suChinese.toString();
    }
}

這段程式碼並不難理解,產生的驗證碼文字類似 1 1=?@2 這樣的字串。

將來以@為分界線,將@前面的字串內容繪製到圖片上,@後面的內容存到 session 中,和用戶上傳的內容進行比較即可。

當然,我們還需要在配置驗證碼的時候添加如下屬性,以修改驗證碼文字的提供類別:

properties.setProperty(KAPTCHA_TEXTPRODUCER_IMPL, "org.javaboy.tienchin.framework.config.KaptchaTextCreator");

配置完成後,將來在介面中直接使用這個驗證碼即可,用的時候注意將產生的驗證碼文字拆分後處理,一部分用來繪圖,一部分用來存到session 中。

以上是SpringBoot+kaptcha怎麼實作驗證碼的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:yisu.com。如有侵權,請聯絡admin@php.cn刪除