Spring Boot中驗證碼實現kaptcha


要生成驗證碼網上的方案比較多,基本是基於兩大類:1為自定義生成,操作用Image類,2為kaptcha生成,有模糊算法。

當然也可以直接交由前端進行處理

1、基於kaptcha

首先不要懷疑的是報名是GitHub還是Google的,因為都是出自私人的產物,並且之前在Google Code進行托管,然后關閉了Google Code之后,有人就把其轉入到GitHub中,並且不只一個人,所以才會造成市面上這么多不同的報名。

但總體功能基本不變。

下面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進行導入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方法是導入XML文件的寫法,普通注解方式不需要這么寫。普通即可。

Controller,生成驗證碼

@Autowired  
DefaultKaptcha defaultKaptcha;

@RequestMapping("/defaultKaptcha")  
public void defaultKaptcha(HttpServletRequest httpServletRequest,HttpServletResponse httpServletResponse) throws Exception{  
            byte[] captchaChallengeAsJpeg = null;    
             ByteArrayOutputStream jpegOutputStream = new ByteArrayOutputStream();    
             try {    
             //生產驗證碼字符串並保存到session中  
             String createText = defaultKaptcha.createText();  
             httpServletRequest.getSession().setAttribute("vrifyCode", createText);  
             //使用生產的驗證碼字符串返回一個BufferedImage對象並轉為byte寫入到byte數組中  
             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數組  
             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();    
}  

驗證方法

@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", "錯誤的驗證碼");  
        andView.setViewName("index");  
    } else {  
        andView.addObject("info", "登錄成功");  
        andView.setViewName("succeed");  
          
    }  
    return andView;  
}  

配置項參考:

kaptcha.border  是否有邊框  默認為true  我們可以自己設置yes,no  
kaptcha.border.color   邊框顏色   默認為Color.BLACK  
kaptcha.border.thickness  邊框粗細度  默認為1  
kaptcha.producer.impl   驗證碼生成器  默認為DefaultKaptcha  
kaptcha.textproducer.impl   驗證碼文本生成器  默認為DefaultTextCreator  
kaptcha.textproducer.char.string   驗證碼文本字符內容范圍  默認為abcde2345678gfynmnpwx  
kaptcha.textproducer.char.length   驗證碼文本字符長度  默認為5  
kaptcha.textproducer.font.names    驗證碼文本字體樣式  默認為new Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize)  
kaptcha.textproducer.font.size   驗證碼文本字符大小  默認為40  
kaptcha.textproducer.font.color  驗證碼文本字符顏色  默認為Color.BLACK  
kaptcha.textproducer.char.space  驗證碼文本字符間距  默認為2  
kaptcha.noise.impl    驗證碼噪點生成對象  默認為DefaultNoise  
kaptcha.noise.color   驗證碼噪點顏色   默認為Color.BLACK  
kaptcha.obscurificator.impl   驗證碼樣式引擎  默認為WaterRipple  
kaptcha.word.impl   驗證碼文本字符渲染   默認為DefaultWordRenderer  
kaptcha.background.impl   驗證碼背景生成器   默認為DefaultBackground  
kaptcha.background.clear.from   驗證碼背景顏色漸進   默認為Color.LIGHT_GRAY  
kaptcha.background.clear.to   驗證碼背景顏色漸進   默認為Color.WHITE  
kaptcha.image.width   驗證碼圖片寬度  默認為200  
kaptcha.image.height  驗證碼圖片高度  默認為50

2、自定義方案

驗證碼生成類

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();
        //生成隨機類
        Random random = new Random();
        // 設定背景色
        g.setColor(getRandColor(200, 250));
        g.fillRect(0, 0, width, height);
        //設定字體
        g.setFont(new Font("Times New Roman", Font.PLAIN, 18));
        // 隨機產生168條干擾線,使圖象中的認證碼不易被其它程序探測到
        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);
        }
        //取隨機產生的碼
        String strEnsure = "";
        //4代表4位驗證碼,如果要生成更多位的認證碼,則加大數值
        for (int i = 0; i < 4; ++i) {
            strEnsure += mapTable[(int) (mapTable.length * Math.random())];
            // 將認證碼顯示到圖象中
            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;
    }
    //給定范圍獲得隨機顏色
    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);
    }
}

獲取驗證碼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;
}

驗證驗證碼API

@RequestMapping(value = "/checkcode")
@ResponseBody
public String checkcode(HttpServletRequest request, HttpSession session) throws Exception {
    String checkCode = request.getParameter("checkCode");
    Object cko = session.getAttribute("simpleCaptcha") ; //驗證碼對象
    if(cko == null){
        request.setAttribute("errorMsg", "驗證碼已失效,請重新輸入!");
        return "驗證碼已失效,請重新輸入!";
    }
    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", "驗證碼錯誤!");
        return "驗證碼錯誤!";
    } else if ((now.getTime()-codeTime)/1000/60>5) {
        //驗證碼有效時長為5分鍾
        request.setAttribute("errorMsg", "驗證碼已失效,請重新輸入!");
        return "驗證碼已失效,請重新輸入!";
    }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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM