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");
配置其實就沒用了,可以不用加。
當然,我們也可以自訂驗證碼文本,只需要提供一個驗證碼文本的實作類別即可,如下:
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中文網其他相關文章!