Java编写极验验证码

来源:互联网 发布:三国杀淘宝 编辑:程序博客网 时间:2024/05/20 22:01

一、去极验注册账号获得ID和key

地址:https://account.geetest.com/


二、导入sdk架包

需要两个架包:java-json.jar  和  servlet-api.jar

下载地址:http://download.csdn.net/download/junmoxi/9949773


三、编写后台代码

StartCaptchaServlet.java  (获得验证码)

package com.lei.servlet;import java.io.IOException;import java.io.PrintWriter;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import com.lei.config.GeetestConfig;import com.lei.sdk.GeetestLib;public class StartCaptchaServlet extends HttpServlet {protected void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {GeetestLib gtSdk = new GeetestLib(GeetestConfig.getGeetest_id(), GeetestConfig.getGeetest_key(), GeetestConfig.isnewfailback());String resStr = "{}";//自定义useridString userid = "test";//进行验证预处理int gtServerStatus = gtSdk.preProcess(userid);//将服务器状态设置到session中request.getSession().setAttribute(gtSdk.gtServerStatusSessionKey, gtServerStatus);//将userid设置到session中request.getSession().setAttribute("userid", userid);resStr = gtSdk.getResponseStr();PrintWriter out = response.getWriter();out.println(resStr);}}
VerifyLoginServlet.java  (验证验证码)


package com.lei.servlet;import java.io.IOException;import java.io.PrintWriter;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.json.JSONException;import org.json.JSONObject;import com.lei.config.GeetestConfig;import com.lei.sdk.GeetestLib;/** * 使用post方式,返回验证结果, request表单中必须包含challenge, validate, seccode */public class VerifyLoginServlet extends HttpServlet {protected void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {GeetestLib gtSdk = new GeetestLib(GeetestConfig.getGeetest_id(), GeetestConfig.getGeetest_key(), GeetestConfig.isnewfailback());String challenge = request.getParameter(GeetestLib.fn_geetest_challenge);String validate = request.getParameter(GeetestLib.fn_geetest_validate);String seccode = request.getParameter(GeetestLib.fn_geetest_seccode);//从session中获取gt-server状态int gt_server_status_code = (Integer) request.getSession().getAttribute(gtSdk.gtServerStatusSessionKey);//从session中获取useridString userid = (String)request.getSession().getAttribute("userid");int gtResult = 0;if (gt_server_status_code == 1) {//gt-server正常,向gt-server进行二次验证gtResult = gtSdk.enhencedValidateRequest(challenge, validate, seccode, userid);System.out.println(gtResult);} else {// gt-server非正常情况下,进行failback模式验证System.out.println("failback:use your own server captcha validate");gtResult = gtSdk.failbackValidateRequest(challenge, validate, seccode);System.out.println(gtResult);}if (gtResult == 1) {// 验证成功PrintWriter out = response.getWriter();JSONObject data = new JSONObject();try {data.put("status", "success");data.put("version", gtSdk.getVersionInfo());} catch (JSONException e) {e.printStackTrace();}out.println(data.toString());}else {// 验证失败JSONObject data = new JSONObject();try {data.put("status", "fail");data.put("version", gtSdk.getVersionInfo());} catch (JSONException e) {e.printStackTrace();}PrintWriter out = response.getWriter();out.println(data.toString());}}}

GeetestConfig.java  (配置文件)

package com.lei.config;import javax.swing.text.StyledEditorKit.BoldAction;/** * GeetestWeb配置文件 *  * */public class GeetestConfig {// 填入自己的captcha_id和private_keyprivate static final String geetest_id = "7e5a9550b98e8496127526b0459d260d";private static final String geetest_key = "354c66612d75838bfebc54f2c9c8d271";private static final boolean newfailback = true;public static final String getGeetest_id() {return geetest_id;}public static final String getGeetest_key() {return geetest_key;}public static final boolean isnewfailback() {return newfailback;}}

GeetestLib.java  (SDK)


package com.lei.sdk;import java.awt.print.Printable;import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.OutputStreamWriter;import java.lang.reflect.GenericArrayType;import java.net.HttpURLConnection;import java.net.InetAddress;import java.net.Socket;import java.net.URL;import java.security.MessageDigest;import java.security.NoSuchAlgorithmException;import java.text.SimpleDateFormat;import java.util.ArrayList;import java.util.HashMap;import java.util.logging.Logger;import javax.print.DocFlavor.STRING;import javax.servlet.descriptor.JspConfigDescriptor;import javax.servlet.http.HttpServletRequest;import org.json.JSONException;import org.json.JSONObject;/** * Java SDK *  */public class GeetestLib {protected final String verName = "4.0";protected final String sdkLang = "java";protected final String apiUrl = "http://api.geetest.com"; protected final String registerUrl = "/register.php"; protected final String validateUrl = "/validate.php";protected final String json_format = "1";     /** * 极验验证二次验证表单数据 chllenge */public static final String fn_geetest_challenge = "geetest_challenge";/** * 极验验证二次验证表单数据 validate */public static final String fn_geetest_validate = "geetest_validate";/** * 极验验证二次验证表单数据 seccode */public static final String fn_geetest_seccode = "geetest_seccode";/** * 公钥 */private String captchaId = "";/** * 私钥 */private String privateKey = "";/** * 是否开启新的failback */private boolean newFailback = false;/** * 返回字符串 */private String responseStr = "";/** * 调试开关,是否输出调试日志 */public boolean debugCode = true;/** * 极验验证API服务状态Session Key */public String gtServerStatusSessionKey = "gt_server_status";/** * 标记字段 */public String userId = "";/** * 标记验证模块所应用的终端类型 */public String clientType = "";/** * 标记用户请求验证时所携带的IP */public String ipAddress  = "";/** * 带参数构造函数 *  * @param captchaId * @param privateKey */public GeetestLib(String captchaId, String privateKey, boolean newFailback) {this.captchaId = captchaId;this.privateKey = privateKey;this.newFailback = newFailback;}/** * 获取本次验证初始化返回字符串 *  * @return 初始化结果 */public String getResponseStr() {return responseStr;}public String getVersionInfo() {return verName;}/** * 预处理失败后的返回格式串 *  * @return */private String getFailPreProcessRes() {Long rnd1 = Math.round(Math.random() * 100);Long rnd2 = Math.round(Math.random() * 100);String md5Str1 = md5Encode(rnd1 + "");String md5Str2 = md5Encode(rnd2 + "");String challenge = md5Str1 + md5Str2.substring(0, 2);JSONObject jsonObject = new JSONObject();try {jsonObject.put("success", 0);jsonObject.put("gt", this.captchaId);jsonObject.put("challenge", challenge);jsonObject.put("new_captcha", this.newFailback);} catch (JSONException e) {gtlog("json dumps error");}return jsonObject.toString();}/** * 预处理成功后的标准串 *  */private String getSuccessPreProcessRes(String challenge) {gtlog("challenge:" + challenge);JSONObject jsonObject = new JSONObject();try {jsonObject.put("success", 1);jsonObject.put("gt", this.captchaId);jsonObject.put("challenge", challenge);} catch (JSONException e) {gtlog("json dumps error");}return jsonObject.toString();}/** * 验证初始化预处理 * * @return 1表示初始化成功,0表示初始化失败 */public int preProcess() {if (registerChallenge() != 1) {this.responseStr = this.getFailPreProcessRes();return 0;}return 1;}/** * 验证初始化预处理 * * @param userid * @return 1表示初始化成功,0表示初始化失败 */public int preProcess(String userid){this.userId = userid;return this.preProcess();}/** * 用captchaID进行注册,更新challenge *  * @return 1表示注册成功,0表示注册失败 */private int registerChallenge() {try {String getUrl = apiUrl + registerUrl + "?";String param = "gt=" + this.captchaId + "&json_format=" + this.json_format;if (this.userId != ""){param = param + "&user_id=" + this.userId;this.userId = "";}if (this.clientType != ""){param = param + "&client_type=" + this.clientType;this.clientType = "";}if (this.ipAddress != ""){param = param + "&ip_address=" + this.ipAddress;this.ipAddress = "";}gtlog("GET_URL:" + getUrl + param);String result_str = readContentFromGet(getUrl + param);if (result_str == "fail"){gtlog("gtServer register challenge failed");return 0;}gtlog("result:" + result_str);JSONObject jsonObject = new JSONObject(result_str);    String return_challenge = jsonObject.getString("challenge");gtlog("return_challenge:" + return_challenge);if (return_challenge.length() == 32) {this.responseStr = this.getSuccessPreProcessRes(this.md5Encode(return_challenge + this.privateKey));    return 1;    }else {gtlog("gtServer register challenge error");return 0;}} catch (Exception e) {gtlog(e.toString());gtlog("exception:register api");}return 0;}/** * 判断一个表单对象值是否为空 *  * @param gtObj * @return */protected boolean objIsEmpty(Object gtObj) {if (gtObj == null) {return true;}if (gtObj.toString().trim().length() == 0) {return true;}return false;}/** * 检查客户端的请求是否合法,三个只要有一个为空,则判断不合法 *  * @param request * @return */private boolean resquestIsLegal(String challenge, String validate, String seccode) {if (objIsEmpty(challenge)) {return false;}if (objIsEmpty(validate)) {return false;}if (objIsEmpty(seccode)) {return false;}return true;}/** * 服务正常的情况下使用的验证方式,向gt-server进行二次验证,获取验证结果 *  * @param challenge * @param validate * @param seccode * @return 验证结果,1表示验证成功0表示验证失败 */public int enhencedValidateRequest(String challenge, String validate, String seccode) {if (!resquestIsLegal(challenge, validate, seccode)) {return 0;}gtlog("request legitimate");String postUrl = this.apiUrl + this.validateUrl;String param = String.format("challenge=%s&validate=%s&seccode=%s&json_format=%s",                      challenge, validate, seccode, this.json_format); String response = "";try {if (validate.length() <= 0) {return 0;}if (!checkResultByPrivate(challenge, validate)) {return 0;}gtlog("checkResultByPrivate");response = readContentFromPost(postUrl, param);gtlog("response: " + response);} catch (Exception e) {e.printStackTrace();}String return_seccode = "";try {JSONObject return_map = new JSONObject(response);return_seccode = return_map.getString("seccode");gtlog("md5: " + md5Encode(return_seccode));if (return_seccode.equals(md5Encode(seccode))) {return 1;} else {return 0;}} catch (JSONException e) {gtlog("json load error");return 0;}}/** * 服务正常的情况下使用的验证方式,向gt-server进行二次验证,获取验证结果 *  * @param challenge * @param validate * @param seccode * @param userid * @return 验证结果,1表示验证成功0表示验证失败 */public int enhencedValidateRequest(String challenge, String validate, String seccode, String userid) {this.userId = userid;return this.enhencedValidateRequest(challenge, validate, seccode);}/** * failback使用的验证方式 *  * @param challenge * @param validate * @param seccode * @return 验证结果,1表示验证成功0表示验证失败 */public int failbackValidateRequest(String challenge, String validate, String seccode) {gtlog("in failback validate");if (!resquestIsLegal(challenge, validate, seccode)) {return 0;}gtlog("request legitimate");return 1;}/** * 输出debug信息,需要开启debugCode *  * @param message */public void gtlog(String message) {if (debugCode) {System.out.println("gtlog: " + message);}}protected boolean checkResultByPrivate(String challenge, String validate) {String encodeStr = md5Encode(privateKey + "geetest" + challenge);return validate.equals(encodeStr);}/** * 发送GET请求,获取服务器返回结果 *  * @param getURL * @return 服务器返回结果 * @throws IOException */private String readContentFromGet(String URL) throws IOException {URL getUrl = new URL(URL);HttpURLConnection connection = (HttpURLConnection) getUrl.openConnection();connection.setConnectTimeout(2000);// 设置连接主机超时(单位:毫秒)connection.setReadTimeout(2000);// 设置从主机读取数据超时(单位:毫秒)// 建立与服务器的连接,并未发送数据connection.connect();if (connection.getResponseCode() == 200) {// 发送数据到服务器并使用Reader读取返回的数据StringBuffer sBuffer = new StringBuffer();InputStream inStream = null;byte[] buf = new byte[1024];inStream = connection.getInputStream();for (int n; (n = inStream.read(buf)) != -1;) {sBuffer.append(new String(buf, 0, n, "UTF-8"));}inStream.close();connection.disconnect();// 断开连接            return sBuffer.toString();}else {return "fail";}}/** * 发送POST请求,获取服务器返回结果 *  * @param getURL * @return 服务器返回结果 * @throws IOException */private String readContentFromPost(String URL, String data) throws IOException {gtlog(data);URL postUrl = new URL(URL);HttpURLConnection connection = (HttpURLConnection) postUrl.openConnection();connection.setConnectTimeout(2000);// 设置连接主机超时(单位:毫秒)connection.setReadTimeout(2000);// 设置从主机读取数据超时(单位:毫秒)connection.setRequestMethod("POST");connection.setDoInput(true);connection.setDoOutput(true);connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");// 建立与服务器的连接,并未发送数据connection.connect(); OutputStreamWriter outputStreamWriter = new OutputStreamWriter(connection.getOutputStream(), "utf-8");   outputStreamWriter.write(data);   outputStreamWriter.flush(); outputStreamWriter.close();if (connection.getResponseCode() == 200) {// 发送数据到服务器并使用Reader读取返回的数据StringBuffer sBuffer = new StringBuffer();InputStream inStream = null;byte[] buf = new byte[1024];inStream = connection.getInputStream();for (int n; (n = inStream.read(buf)) != -1;) {sBuffer.append(new String(buf, 0, n, "UTF-8"));}inStream.close();connection.disconnect();// 断开连接            return sBuffer.toString();}else {return "fail";}}/** * md5 加密 *  * @time 2014年7月10日 下午3:30:01 * @param plainText * @return */private String md5Encode(String plainText) {String re_md5 = new String();try {MessageDigest md = MessageDigest.getInstance("MD5");md.update(plainText.getBytes());byte b[] = md.digest();int i;StringBuffer buf = new StringBuffer("");for (int offset = 0; offset < b.length; offset++) {i = b[offset];if (i < 0)i += 256;if (i < 16)buf.append("0");buf.append(Integer.toHexString(i));}re_md5 = buf.toString();} catch (NoSuchAlgorithmException e) {e.printStackTrace();}return re_md5;}}

四、前台代码

login.jsp

<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%><%String path = request.getContextPath();String basePath = request.getScheme() + "://"+ request.getServerName() + ":" + request.getServerPort()+ path + "/";%><!DOCTYPE html><html><head>    <meta charset="UTF-8">    <meta name="viewport" content="width=device-width, initial-scale=1">    <title>gt-node-sdk-demo</title>    <style>        body {            margin: 50px 0;            text-align: center;            font-family: "PingFangSC-Regular", "Open Sans", Arial, "Hiragino Sans GB", "Microsoft YaHei", "STHeiti", "WenQuanYi Micro Hei", SimSun, sans-serif;        }        .inp {            border: 1px solid #cccccc;            border-radius: 2px;            padding: 0 10px;            width: 278px;            height: 40px;            font-size: 18px;        }        .btn {            border: 1px solid #cccccc;            border-radius: 2px;            width: 100px;            height: 40px;            font-size: 16px;            color: #666;            cursor: pointer;            background: white linear-gradient(180deg, #ffffff 0%, #f3f3f3 100%);        }        .btn:hover {            background: white linear-gradient(0deg, #ffffff 0%, #f3f3f3 100%)        }        #captcha1,        #captcha2 {            width: 300px;            display: inline-block;        }        .show {            display: block;        }        .hide {            display: none;        }        #notice1,        #notice2 {            color: red;        }        label {            vertical-align: top;            display: inline-block;            width: 80px;            text-align: right;        }        #wait1, #wait2 {            text-align: left;            color: #666;            margin: 0;        }    </style></head><body><h1>极验验证SDKDemo</h1><hr><form action="gt/ajax-validate1" method="post">    <h2>大图点击Demo,使用表单进行二次验证</h2>    <br>    <div>        <label for="username1">用户名:</label>        <input class="inp" id="username1" type="text" value="极验验证">    </div>    <br>    <div>        <label for="password1">密码:</label>        <input class="inp" id="password1" type="password" value="123456">    </div>    <br>    <div>        <label>完成验证:</label>        <div id="captcha1">            <p id="wait1" class="show">正在加载验证码......</p>        </div>    </div>    <br>    <p id="notice1" class="hide">请先完成验证</p>    <input class="btn" id="submit1" type="submit" value="提交"></form><!-- 注意,验证码本身是不需要 jquery 库,此处使用 jquery 仅为了在 demo 使用,减少代码量 --><script src="http://apps.bdimg.com/libs/jquery/1.9.1/jquery.js"></script><!-- 引入 gt.js,既可以使用其中提供的 initGeetest 初始化函数 --><script src="<%=request.getContextPath() %>/gt.js"></script><script>    var handler1 = function (captchaObj) {        $("#submit1").click(function (e) {            var result = captchaObj.getValidate();            if (!result) {                $("#notice1").show();                setTimeout(function () {                    $("#notice1").hide();                }, 2000);                e.preventDefault();            }        });        // 将验证码加到id为captcha的元素里,同时会有三个input的值用于表单提交        captchaObj.appendTo("#captcha1");        captchaObj.onReady(function () {            $("#wait1").hide();        });        // 更多接口参考:http://www.geetest.com/install/sections/idx-client-sdk.html    };    $.ajax({        url: "gt/register1?t=" + (new Date()).getTime(), // 加随机数防止缓存        type: "get",        dataType: "json",        success: function (data) {            // 调用 initGeetest 初始化参数            // 参数1:配置参数            // 参数2:回调,回调的第一个参数验证码对象,之后可以使用它调用相应的接口            initGeetest({                gt: data.gt,                challenge: data.challenge,                new_captcha: data.new_captcha, // 用于宕机时表示是新验证码的宕机                offline: !data.success, // 表示用户后台检测极验服务器是否宕机,一般不需要关注                product: "float", // 产品形式,包括:float,popup                width: "100%"                // 更多配置参数请参见:http://www.geetest.com/install/sections/idx-client-sdk.html#config            }, handler1);        }    });</script><br><br><hr><form>    <h2>滑动demo,使用ajax进行二次验证</h2>    <br>    <div>        <label for="username2">用户名:</label>        <input class="inp" id="username2" type="text" value="极验验证">    </div>    <br>    <div>        <label for="password2">密码:</label>        <input class="inp" id="password2" type="password" value="123456">    </div>    <br>    <div>        <label>完成验证:</label>        <div id="captcha2">            <p id="wait2" class="show">正在加载验证码......</p>        </div>    </div>    <br>    <p id="notice2" class="hide">请先完成验证</p>    <input class="btn" id="submit2" type="submit" value="提交"></form><script>    var handler2 = function (captchaObj) {        $("#submit2").click(function (e) {            var result = captchaObj.getValidate();            if (!result) {                $("#notice2").show();                setTimeout(function () {                    $("#notice2").hide();                }, 2000);            } else {                $.ajax({                    url: 'gt/ajax-validate2',                    type: 'POST',                    dataType: 'json',                    data: {                        username: $('#username2').val(),                        password: $('#password2').val(),                        geetest_challenge: result.geetest_challenge,                        geetest_validate: result.geetest_validate,                        geetest_seccode: result.geetest_seccode                    },                    success: function (data) {                        if (data.status === 'success') {                            alert('登录成功');                        } else if (data.status === 'fail') {                            alert('登录失败');                        }                    }                })            }            e.preventDefault();        });        // 将验证码加到id为captcha的元素里,同时会有三个input的值用于表单提交        captchaObj.appendTo("#captcha2");        captchaObj.onReady(function () {            $("#wait2").hide();        });        // 更多接口参考:http://www.geetest.com/install/sections/idx-client-sdk.html    };    $.ajax({        url: "gt/register2?t=" + (new Date()).getTime(), // 加随机数防止缓存        type: "get",        dataType: "json",        success: function (data) {            // 调用 initGeetest 初始化参数            // 参数1:配置参数            // 参数2:回调,回调的第一个参数验证码对象,之后可以使用它调用相应的接口            initGeetest({                gt: data.gt,                challenge: data.challenge,                new_captcha: data.new_captcha, // 用于宕机时表示是新验证码的宕机                offline: !data.success, // 表示用户后台检测极验服务器是否宕机,一般不需要关注                product: "popup", // 产品形式,包括:float,popup                width: "100%"                // 更多配置参数请参见:http://www.geetest.com/install/sections/idx-client-sdk.html#config            }, handler2);        }    });</script></body></html>

需要一个js文件,gt.js

运行结果




下载地址和Demo都可以在下面的地址下载 到

http://download.csdn.net/download/junmoxi/9949773