驗證碼是咱們作人機驗證最經常使用的方式,經常使用於敏感操做的驗證,好比:登陸、註冊、修改等。html
驗證碼的原理:不一樣的客戶端擁有不一樣的 session 對象,在看到驗證碼圖片的時刻,服務器後端代碼生成圖片並將隨機字符存儲到 session 中。這樣客戶端看到的只能是圖片,人工識別圖片後將字符發送到服務器與 session 中的字符進行比對。java
上面只是簡單的介紹了驗證碼的原理,更多細節還需有 javaweb 相關基礎知識,這篇文章適合有基礎的同窗。git
最近幾天我翻到了之前生成驗證碼的工具類,使用 Graphics2D 生成的圖片,而後再以流的形式寫出到客戶端,這些代碼仍是有些問題的,都是硬編碼。在之後的使用中咱們可能有不一樣的需求都會致使代碼從新修改,自定義一些樣式都不是很方便。github
因此我找到了 github 上的一個生成驗證碼的工具:kaptcha,下面我就給你們介紹一下 kaptcha 的使用。web
咱們就以一個 maven 構建的 web 項目爲例後端
在 pom.xml 文件中添加相關依賴服務器
<dependency> <groupId>com.github.penggle</groupId> <artifactId>kaptcha</artifactId> <version>2.3.2</version> </dependency>
修改 web.xml,添加 kaptcha 提供的 servlet 並配置映射路徑session
<servlet> <servlet-name>Kaptcha</servlet-name> <servlet-class>com.google.code.kaptcha.servlet.KaptchaServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>Kaptcha</servlet-name> <url-pattern>/captcha</url-pattern> </servlet-mapping>
訪問 http://localhost:8080/captcha 這時發現就已經能夠產生驗證碼了,但還有個問題,驗證碼的隨機字符存在哪裏了?app
咱們來查看 KaptchaServlet 這個類的源碼,doGet 方法maven
@Override public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // Set to expire far in the past. resp.setDateHeader("Expires", 0); // Set standard HTTP/1.1 no-cache headers. resp.setHeader("Cache-Control", "no-store, no-cache, must-revalidate"); // Set IE extended HTTP/1.1 no-cache headers (use addHeader). resp.addHeader("Cache-Control", "post-check=0, pre-check=0"); // Set standard HTTP/1.0 no-cache header. resp.setHeader("Pragma", "no-cache"); // return a jpeg resp.setContentType("image/jpeg"); // create the text for the image String capText = this.kaptchaProducer.createText(); // store the text in the session req.getSession().setAttribute(this.sessionKeyValue, capText); // store the date in the session so that it can be compared // against to make sure someone hasn't taken too long to enter // their kaptcha req.getSession().setAttribute(this.sessionKeyDateValue, new Date()); // create the image with the text BufferedImage bi = this.kaptchaProducer.createImage(capText); ServletOutputStream out = resp.getOutputStream(); // write the data out ImageIO.write(bi, "jpg", out); }
有這樣一段代碼,獲取字符後存入 session 中,鍵爲 sessionKeyValue
這個變量的值
// create the text for the image String capText = this.kaptchaProducer.createText(); // store the text in the session req.getSession().setAttribute(this.sessionKeyValue, capText);
sessionKeyValue
這個變量的值在 init 方法中被賦值
this.sessionKeyValue = config.getSessionKey();
好咱們進入 config.getSessionKey()
中查看代碼,發現 session 的鍵爲 Constants 這個類中的常量 Constants.KAPTCHA_SESSION_KEY
return this.properties.getProperty(Constants.KAPTCHA_SESSION_CONFIG_KEY, Constants.KAPTCHA_SESSION_KEY);
咱們來驗證一下,編寫一個 servlet
import com.google.code.kaptcha.Constants; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; @WebServlet("/test") public class TestKaptchaServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html;charset=utf-8"); PrintWriter out = resp.getWriter(); //獲取傳入的驗證碼 String captcha = req.getParameter("captcha"); if (null != captcha) { //獲取實際session中的驗證碼 String code = (String) req.getSession().getAttribute(Constants.KAPTCHA_SESSION_KEY); if (null == code){ resp.sendRedirect("/captcha"); return; } if (code.equalsIgnoreCase(captcha)) { out.print("驗證輸入正確"); } else { out.print("驗證碼輸入有誤"); } } else { out.print("必須輸入驗證碼"); } out.flush(); out.close(); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doGet(req, resp); } }
先訪問驗證碼 http://localhost:8080/captcha 而後訪問 http://localhost:8080/test?captcha=驗證碼
以上這些默認配置能知足通常業務的使用了,下面經過深刻解析 kaptcha 的源碼自定義配置驗證碼的寬、高、邊框、顏色、字符等
再來看一下 init 方法中的代碼
@Override public void init(ServletConfig conf) throws ServletException { super.init(conf); // Switch off disk based caching. ImageIO.setUseCache(false); Enumeration<?> initParams = conf.getInitParameterNames(); while (initParams.hasMoreElements()) { String key = (String) initParams.nextElement(); String value = conf.getInitParameter(key); this.props.put(key, value); } Config config = new Config(this.props); this.kaptchaProducer = config.getProducerImpl(); this.sessionKeyValue = config.getSessionKey(); this.sessionKeyDateValue = config.getSessionDate(); }
這段代碼獲取 servlet 的初始化參數,並將參數存入 config 對象中,看 config 中的一段代碼
public boolean isBorderDrawn() { String paramName = Constants.KAPTCHA_BORDER; String paramValue = this.properties.getProperty(paramName); return this.helper.getBoolean(paramName, paramValue, true); }
沒錯,全部的參數名字都是 Constants 類中常量名稱
public class Constants { public final static String KAPTCHA_SESSION_KEY = "KAPTCHA_SESSION_KEY"; public final static String KAPTCHA_SESSION_DATE = "KAPTCHA_SESSION_DATE"; public final static String KAPTCHA_SESSION_CONFIG_KEY = "kaptcha.session.key"; //省略其餘代碼 }
因此,能夠給 KaptchaServlet
在 web.xml 配置參數,下面這些配置給你們參考
<servlet> <servlet-name>Kaptcha</servlet-name> <servlet-class>com.google.code.kaptcha.servlet.KaptchaServlet</servlet-class> <!-- 是否有邊框 --> <init-param> <param-name>kaptcha.border</param-name> <param-value>no</param-value> </init-param> <!-- 字體顏色 --> <init-param> <param-name>kaptcha.textproducer.font.color</param-name> <param-value>red</param-value> </init-param> <!-- 圖片寬度 --> <init-param> <param-name>kaptcha.image.width</param-name> <param-value>135</param-value> </init-param> <!-- 使用哪些字符生成驗證碼 --> <init-param> <param-name>kaptcha.textproducer.char.string</param-name> <param-value>ACDEFHKPRSTWX345679</param-value> </init-param> <!-- 圖片高度 --> <init-param> <param-name>kaptcha.image.height</param-name> <param-value>50</param-value> </init-param> <!-- 字體大小 --> <init-param> <param-name>kaptcha.textproducer.font.size</param-name> <param-value>38</param-value> </init-param> <!-- 干擾線的顏色 --> <init-param> <param-name>kaptcha.noise.color</param-name> <param-value>black</param-value> </init-param> <!-- 字符個數 --> <init-param> <param-name>kaptcha.textproducer.char.length</param-name> <param-value>6</param-value> </init-param> <!-- 使用哪些字體 --> <init-param> <param-name>kaptcha.textproducer.font.names</param-name> <param-value>Arial</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>Kaptcha</servlet-name> <url-pattern>/captcha</url-pattern> </servlet-mapping>
原文出處:https://www.cnblogs.com/AIThink/p/10476492.html