一、去极验注册账号获得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 = "{}";
//自定义userid
String 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中获取userid
String 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_key
private 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