java spring jcaptcha 圖型驗證碼

jcaptcha與spring結合實作

黃昭宏 2016/09/09 00:09:38
2065







主題:

jcaptcha與spring結合實作

文章簡介:

在既有的spring登入畫面中加入圖型驗證碼

作者:

Zackily Huang

版本/產出日期

V1.0/2016.09.08




前言

驗證碼的技術隨著社群網站的興起也越來越普及,所以基於JAVA開發的API也越來越多,今天要介紹的就是免費且易於實作的JCaptcha

目的

在實作使用者登錄的頁面時,為了防止機器人程式的惡意行為如破解使用者帳戶密碼或者在論壇做惡意評論,常會加入驗證碼的使用。

開始前準備

開發工具:Eclipse IDE

測試環境:Tomcat 6

        

本文

1、 安裝JCaptcha
將下列二個dependency加入pom.xml

<!--Jcaptcha -->

<dependency>

<groupId>com.octo.captcha</groupId>

<artifactId>jcaptcha-api</artifactId>

<version>1.0</version>

</dependency>

<dependency>

<groupId>com.octo.captcha</groupId>

<artifactId>jcaptcha</artifactId>

<version>2.0-alpha-1</version>

</dependency>


2、 實作CaptchaService
注意:這個service必須為一個singleton類別


import com.octo.captcha.service.captchastore.FastHashMapCaptchaStore;

import com.octo.captcha.service.image.DefaultManageableImageCaptchaService;

import com.octo.captcha.service.image.ImageCaptchaService;

import com.taiwanmobile.beacon.portal.util.CaptchaEngineEx;


public class CaptchaServiceSingleton {

    private static ImageCaptchaService instance;


    static {

        instance = new DefaultManageableImageCaptchaService(

new FastHashMapCaptchaStore(), new CaptchaEngineEx(),

180, 100000, 75000);

    }


    public static ImageCaptchaService getInstance() {

        return instance;

    }

}


3、 實作ListImageCaptchaEngine

import java.awt.Font;


import com.octo.captcha.component.image.backgroundgenerator.BackgroundGenerator;

import com.octo.captcha.component.image.backgroundgenerator.FunkyBackgroundGenerator;

import com.octo.captcha.component.image.color.RandomRangeColorGenerator;

import com.octo.captcha.component.image.fontgenerator.FontGenerator;

import com.octo.captcha.component.image.fontgenerator.RandomFontGenerator;

import com.octo.captcha.component.image.textpaster.RandomTextPaster;

import com.octo.captcha.component.image.textpaster.TextPaster;

import com.octo.captcha.component.image.wordtoimage.ComposedWordToImage;

import com.octo.captcha.component.image.wordtoimage.WordToImage;

import com.octo.captcha.component.word.wordgenerator.RandomWordGenerator;

import com.octo.captcha.component.word.wordgenerator.WordGenerator;

import com.octo.captcha.engine.image.ListImageCaptchaEngine;

import com.octo.captcha.image.gimpy.GimpyFactory;


/**

* @author zackily

* 圖型驗證碼產生器主程式

*

*/

public class CaptchaEngineEx extends ListImageCaptchaEngine {

    @SuppressWarnings("deprecation")

    protected void buildInitialFactories() {

        /* 要用來產生驗證碼的隨機字元產生器 */

        WordGenerator wgen =

new RandomWordGenerator("1234567890123456789012345678901234567890");

        /*

         * 要用在驗證碼字元的隨機顏色產生器

         * new int[] {0, 100}《顏色較深較易辨視

         * new int[] {0, 200}《顏色較淺較難辨視

         */

RandomRangeColorGenerator cgen = new RandomRangeColorGenerator(

new int[] {0, 100},

new int[] {0, 100},

new int[] {0, 100});

        /*

         * RandomTextPaster(Integer minAcceptedWordLength, Integer

         * maxAcceptedWordLength, ColorGenerator colorGenerator, Boolean

         * manageColorPerGlyph)

         * minAcceptedWordLength驗證碼字元最少產生字元數

         * maxAcceptedWordLength驗證碼字元最多產生字元數

         */

TextPaster textPaster = new RandomTextPaster(new Integer(4),

new Integer(4),

cgen, true);

        /*

         * FunkyBackgroundGenerator(Integer width, Integer height)

         * 產生驗證碼的圖片尺寸

         * width寬度

         * height長度

         */

BackgroundGenerator backgroundGenerator = new FunkyBackgroundGenerator(

new Integer(120), new Integer(60));

        /* 要用來產生驗證碼的隨機字型陣列 */

Font[] fontsList = new Font[] {

new Font("nyala", Font.ITALIC, 10),

new Font("Bell MT", Font.PLAIN, 10),

new Font("Credit valley", Font.BOLD, 10),

};

        /*

         * RandomFontGenerator(Integer minFontSize, Integer maxFontSize,

Font[] fontsList)

         * 驗證碼產生器

         * minFontSize最小字元尺寸

         * maxFontSize最大字元尺寸

         */

FontGenerator fontGenerator = new RandomFontGenerator(new Integer(20),

new Integer(35),

fontsList);


WordToImage wordToImage = new ComposedWordToImage(fontGenerator,

backgroundGenerator,

textPaster);

this.addFactory(new GimpyFactory(wgen, wordToImage));

    }

}


4、 在登入頁加入圖型驗證碼

<input type="text" name="jcaptcha" value="" />

<img src="generatImage" width="120" height="60">


5、 實作圖型驗證碼Servlet
這個method是用來產生圖型驗證碼的圖片

@RequestMapping(value = "/generatImage")

public void ImageCaptcha(HttpServletRequest request, HttpServletResponse response, Model model)

            throws ServletException, IOException {


        byte[] captchaChallengeAsJpeg = null;

        // the output stream to render the captcha image as jpeg into

        ByteArrayOutputStream jpegOutputStream = new ByteArrayOutputStream();

        // get the session id that will identify the generated captcha.

        // the same id must be used to validate the response, the session id

        // is a good candidate!

        String captchaId = request.getSession().getId();

        // call the ImageCaptchaService getChallenge method

        BufferedImage challenge = CaptchaServiceSingleton.getInstance()

.getImageChallengeForID(captchaId, request.getLocale());


        // a jpeg encoder

        JPEGImageEncoder jpegEncoder = JPEGCodec

.createJPEGEncoder(jpegOutputStream);

        jpegEncoder.encode(challenge);


        captchaChallengeAsJpeg = jpegOutputStream.toByteArray();

        // flush it in the response

        response.setHeader("Cache-Control", "no-store");

        response.setHeader("Pragma", "no-cache");

        response.setDateHeader("Expires", 0);

        response.setContentType("image/jpeg");

        ServletOutputStream responseOutputStream = response.getOutputStream();

        responseOutputStream.write(captchaChallengeAsJpeg);

        responseOutputStream.flush();

        responseOutputStream.close();

}


6、 在登入的method中驗證使用者輸入的驗證碼是否正確,如果不正確就輸出錯誤碼。

String captchaId = request.getSession().getId();

String userCaptchaResponse = request.getParameter("jcaptcha");

boolean captchaPassed = CaptchaServiceSingleton.getInstance()

.validateResponseForID(captchaId, userCaptchaResponse);

if (!captchaPassed) {

    return "redirect:/auth/login.do?user=" + account + "&aaMsg=JCAERR";

}


參考來源

5 minutes application integration tutorial

https://jcaptcha.atlassian.net/wiki/display/general/5+minutes+application+integration+tutorial


黃昭宏