javascript
Spring Boot中验证码实现kaptcha
要生成驗(yàn)證碼網(wǎng)上的方案比較多,基本是基于兩大類:1為自定義生成,操作用Image類,2為kaptcha生成,有模糊算法。
當(dāng)然也可以直接交由前端進(jìn)行處理
1、基于kaptcha
首先不要懷疑的是報(bào)名是GitHub還是Google的,因?yàn)槎际浅鲎运饺说漠a(chǎn)物,并且之前在Google Code進(jìn)行托管,然后關(guān)閉了Google Code之后,有人就把其轉(zhuǎn)入到GitHub中,并且不只一個人,所以才會造成市面上這么多不同的報(bào)名。
但總體功能基本不變。
下面POM先引入包:
<!-- https://mvnrepository.com/artifact/com.github.penggle/kaptcha --> <dependency><groupId>com.github.penggle</groupId><artifactId>kaptcha</artifactId><version>2.3.2</version> </dependency>這個包也不要懷疑,在GitHub上的星星是最多的。
KaptchaConfig.java
import java.util.Properties; import org.springframework.context.annotation.Bean; import org.springframework.stereotype.Component; import com.google.code.kaptcha.impl.DefaultKaptcha; import com.google.code.kaptcha.util.Config; @Component public class KaptchaConfig { @Bean public DefaultKaptcha getDefaultKaptcha(){ com.google.code.kaptcha.impl.DefaultKaptcha defaultKaptcha = new com.google.code.kaptcha.impl.DefaultKaptcha(); Properties properties = new Properties(); properties.setProperty("kaptcha.border", "yes"); properties.setProperty("kaptcha.border.color", "105,179,90"); properties.setProperty("kaptcha.textproducer.font.color", "blue"); properties.setProperty("kaptcha.image.width", "110"); properties.setProperty("kaptcha.image.height", "40"); properties.setProperty("kaptcha.textproducer.font.size", "30"); properties.setProperty("kaptcha.session.key", "code"); properties.setProperty("kaptcha.textproducer.char.length", "4"); properties.setProperty("kaptcha.textproducer.font.names", "宋體,楷體,微軟雅黑"); Config config = new Config(properties); defaultKaptcha.setConfig(config); return defaultKaptcha; } }這個配置文件可以寫成XML,然后通過在main方法使用@ImportResource進(jìn)行導(dǎo)入XML配置:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="captchaProducer" class="com.google.code.kaptcha.impl.DefaultKaptcha"> <property name="config"> <bean class="com.google.code.kaptcha.util.Config"> <constructor-arg type="java.util.Properties"> <props> <prop key = "kaptcha.border ">yes</prop> <prop key="kaptcha.border.color">105,179,90</prop> <prop key="kaptcha.textproducer.font.color">blue</prop> <prop key="kaptcha.image.width">100</prop> <prop key="kaptcha.image.height">50</prop> <prop key="kaptcha.textproducer.font.size">27</prop> <prop key="kaptcha.session.key">code</prop> <prop key="kaptcha.textproducer.char.length">4</prop> <prop key="kaptcha.textproducer.font.names">宋體,楷體,微軟雅黑</prop> <prop key="kaptcha.textproducer.char.string">0123456789ABCEFGHIJKLMNOPQRSTUVWXYZ</prop> <prop key="kaptcha.obscurificator.impl">com.google.code.kaptcha.impl.WaterRipple</prop> <prop key="kaptcha.noise.color">black</prop> <prop key="kaptcha.noise.impl">com.google.code.kaptcha.impl.DefaultNoise</prop> <prop key="kaptcha.background.clear.from">185,56,213</prop> <prop key="kaptcha.background.clear.to">white</prop> <prop key="kaptcha.textproducer.char.space">3</prop> </props> </constructor-arg> </bean> </property> </bean> </beans> @SpringBootApplication @ImportResource(locations={"classpath:mykaptcha.xml"}) public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }注意:以上的main方法是導(dǎo)入XML文件的寫法,普通注解方式不需要這么寫。普通即可。
Controller,生成驗(yàn)證碼
@Autowired DefaultKaptcha defaultKaptcha;@RequestMapping("/defaultKaptcha") public void defaultKaptcha(HttpServletRequest httpServletRequest,HttpServletResponse httpServletResponse) throws Exception{ byte[] captchaChallengeAsJpeg = null; ByteArrayOutputStream jpegOutputStream = new ByteArrayOutputStream(); try { //生產(chǎn)驗(yàn)證碼字符串并保存到session中 String createText = defaultKaptcha.createText(); httpServletRequest.getSession().setAttribute("vrifyCode", createText); //使用生產(chǎn)的驗(yàn)證碼字符串返回一個BufferedImage對象并轉(zhuǎn)為byte寫入到byte數(shù)組中 BufferedImage challenge = defaultKaptcha.createImage(createText); ImageIO.write(challenge, "jpg", jpegOutputStream); } catch (IllegalArgumentException e) { httpServletResponse.sendError(HttpServletResponse.SC_NOT_FOUND); return; } //定義response輸出類型為image/jpeg類型,使用response輸出流輸出圖片的byte數(shù)組 captchaChallengeAsJpeg = jpegOutputStream.toByteArray(); httpServletResponse.setHeader("Cache-Control", "no-store"); httpServletResponse.setHeader("Pragma", "no-cache"); httpServletResponse.setDateHeader("Expires", 0); httpServletResponse.setContentType("image/jpeg"); ServletOutputStream responseOutputStream = httpServletResponse.getOutputStream(); responseOutputStream.write(captchaChallengeAsJpeg); responseOutputStream.flush(); responseOutputStream.close(); }驗(yàn)證方法
@RequestMapping("/imgvrifyControllerDefaultKaptcha") public ModelAndView imgvrifyControllerDefaultKaptcha(HttpServletRequest httpServletRequest,HttpServletResponse httpServletResponse){ ModelAndView andView = new ModelAndView(); String captchaId = (String) httpServletRequest.getSession().getAttribute("vrifyCode"); String parameter = httpServletRequest.getParameter("vrifyCode"); System.out.println("Session vrifyCode "+captchaId+" form vrifyCode "+parameter); if (!captchaId.equals(parameter)) { andView.addObject("info", "錯誤的驗(yàn)證碼"); andView.setViewName("index"); } else { andView.addObject("info", "登錄成功"); andView.setViewName("succeed"); } return andView; }配置項(xiàng)參考:
kaptcha.border 是否有邊框 默認(rèn)為true 我們可以自己設(shè)置yes,no kaptcha.border.color 邊框顏色 默認(rèn)為Color.BLACK kaptcha.border.thickness 邊框粗細(xì)度 默認(rèn)為1 kaptcha.producer.impl 驗(yàn)證碼生成器 默認(rèn)為DefaultKaptcha kaptcha.textproducer.impl 驗(yàn)證碼文本生成器 默認(rèn)為DefaultTextCreator kaptcha.textproducer.char.string 驗(yàn)證碼文本字符內(nèi)容范圍 默認(rèn)為abcde2345678gfynmnpwx kaptcha.textproducer.char.length 驗(yàn)證碼文本字符長度 默認(rèn)為5 kaptcha.textproducer.font.names 驗(yàn)證碼文本字體樣式 默認(rèn)為new Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize) kaptcha.textproducer.font.size 驗(yàn)證碼文本字符大小 默認(rèn)為40 kaptcha.textproducer.font.color 驗(yàn)證碼文本字符顏色 默認(rèn)為Color.BLACK kaptcha.textproducer.char.space 驗(yàn)證碼文本字符間距 默認(rèn)為2 kaptcha.noise.impl 驗(yàn)證碼噪點(diǎn)生成對象 默認(rèn)為DefaultNoise kaptcha.noise.color 驗(yàn)證碼噪點(diǎn)顏色 默認(rèn)為Color.BLACK kaptcha.obscurificator.impl 驗(yàn)證碼樣式引擎 默認(rèn)為WaterRipple kaptcha.word.impl 驗(yàn)證碼文本字符渲染 默認(rèn)為DefaultWordRenderer kaptcha.background.impl 驗(yàn)證碼背景生成器 默認(rèn)為DefaultBackground kaptcha.background.clear.from 驗(yàn)證碼背景顏色漸進(jìn) 默認(rèn)為Color.LIGHT_GRAY kaptcha.background.clear.to 驗(yàn)證碼背景顏色漸進(jìn) 默認(rèn)為Color.WHITE kaptcha.image.width 驗(yàn)證碼圖片寬度 默認(rèn)為200 kaptcha.image.height 驗(yàn)證碼圖片高度 默認(rèn)為502、自定義方案
驗(yàn)證碼生成類
import java.awt.*; import java.awt.image.BufferedImage; import java.io.OutputStream;import java.util.HashMap; import java.util.Map;import java.util.Random;public class ImageCode {private static char mapTable[] = {'0', '1', '2', '3', '4', '5','6', '7', '8', '9', '0', '1','2', '3', '4', '5', '6', '7','8', '9'};public static Map<String, Object> getImageCode(int width, int height, OutputStream os) {Map<String,Object> returnMap = new HashMap<String, Object>();if (width <= 0) width = 60;if (height <= 0) height = 20;BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);// 獲取圖形上下文Graphics g = image.getGraphics();//生成隨機(jī)類Random random = new Random();// 設(shè)定背景色g.setColor(getRandColor(200, 250));g.fillRect(0, 0, width, height);//設(shè)定字體g.setFont(new Font("Times New Roman", Font.PLAIN, 18));// 隨機(jī)產(chǎn)生168條干擾線,使圖象中的認(rèn)證碼不易被其它程序探測到g.setColor(getRandColor(160, 200));for (int i = 0; i < 168; i++) {int x = random.nextInt(width);int y = random.nextInt(height);int xl = random.nextInt(12);int yl = random.nextInt(12);g.drawLine(x, y, x + xl, y + yl);}//取隨機(jī)產(chǎn)生的碼String strEnsure = "";//4代表4位驗(yàn)證碼,如果要生成更多位的認(rèn)證碼,則加大數(shù)值for (int i = 0; i < 4; ++i) {strEnsure += mapTable[(int) (mapTable.length * Math.random())];// 將認(rèn)證碼顯示到圖象中g.setColor(new Color(20 + random.nextInt(110), 20 + random.nextInt(110), 20 + random.nextInt(110)));//直接生成String str = strEnsure.substring(i, i + 1);g.drawString(str, 13 * i + 6, 16);}// 釋放圖形上下文 g.dispose();returnMap.put("image",image);returnMap.put("strEnsure",strEnsure);return returnMap;}//給定范圍獲得隨機(jī)顏色static Color getRandColor(int fc, int bc) {Random random = new Random();if (fc > 255) fc = 255;if (bc > 255) bc = 255;int r = fc + random.nextInt(bc - fc);int g = fc + random.nextInt(bc - fc);int b = fc + random.nextInt(bc - fc);return new Color(r, g, b);} }獲取驗(yàn)證碼API
@RequestMapping(value = "/images/imagecode") public String imagecode(HttpServletRequest request, HttpServletResponse response) throws Exception {OutputStream os = response.getOutputStream();Map<String,Object> map = ImageCode.getImageCode(60, 20, os);String simpleCaptcha = "simpleCaptcha";request.getSession().setAttribute(simpleCaptcha, map.get("strEnsure").toString().toLowerCase());request.getSession().setAttribute("codeTime",new Date().getTime());try {ImageIO.write((BufferedImage) map.get("image"), "JPEG", os);} catch (IOException e) {return "";}return null; }驗(yàn)證驗(yàn)證碼API
@RequestMapping(value = "/checkcode") @ResponseBody public String checkcode(HttpServletRequest request, HttpSession session) throws Exception {String checkCode = request.getParameter("checkCode");Object cko = session.getAttribute("simpleCaptcha") ; //驗(yàn)證碼對象if(cko == null){request.setAttribute("errorMsg", "驗(yàn)證碼已失效,請重新輸入!");return "驗(yàn)證碼已失效,請重新輸入!";}String captcha = cko.toString();Date now = new Date();Long codeTime = Long.valueOf(session.getAttribute("codeTime")+"");if(StringUtils.isEmpty(checkCode) || captcha == null || !(checkCode.equalsIgnoreCase(captcha))) {request.setAttribute("errorMsg", "驗(yàn)證碼錯誤!");return "驗(yàn)證碼錯誤!";} else if ((now.getTime()-codeTime)/1000/60>5) {//驗(yàn)證碼有效時長為5分鐘request.setAttribute("errorMsg", "驗(yàn)證碼已失效,請重新輸入!");return "驗(yàn)證碼已失效,請重新輸入!";}else {session.removeAttribute("simpleCaptcha");return "1";} }?
?
參考:
http://blog.csdn.net/u014104286/article/details/70515004
http://blog.csdn.net/liunian02050328/article/details/53462053
http://www.jb51.net/article/115800.htm
http://blog.csdn.net/rambo_china/article/details/7720181
http://www.jianshu.com/p/7a37077a41e4
http://www.voidcn.com/article/p-ewnhqlod-bmc.html
==>如有問題,請聯(lián)系我:easonjim#163.com,或者下方發(fā)表評論。<==總結(jié)
以上是生活随笔為你收集整理的Spring Boot中验证码实现kaptcha的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ES6的 super 关键字
- 下一篇: truelicense中的maven配置