geetest极验验证-java使用笔记
业务场景
在系统业务中,需要想客户发送手机验证码,进行验证后,才能提交。但为了防止不正当的短信发送(攻击,恶意操作等),需要在发送短信前添加一个行为验证(这里使用的是 极验);
参考文档:
极验行为验证文档:https://docs.geetest.com/install/overview/start/
极验demo:https://www.geetest.com/demo/
步骤:
这里参考下 官方流程,前面的注册验证就不说了,直接重点
搭建geetest的后台
首先从Github: gt3-python-sdk下载.zip
文件 ,用于后台搭建
- gt3-java-sdk-master\src\sdk\GeetestLib.java 这个文件相当java中的实体类,直接放在我的domain文件下。
- gt3-java-sdk-master\src\demo\demo1\GeetestConfig.java ,是geetest的配置文件,用来放我们在极验后台注册应用得到的captcha_id和private_key。
- VerifyLoginServlet.java(验证) 和 StartCaptchaServlet.java(初始化),这两个文件就是两个servlet,我直接放到了我写的一个Controller里面;
import com.jhly.common.config.GeetestConfig;
import com.jhly.common.domain.GeetestLib;
import org.activiti.engine.impl.util.json.JSONException;
import org.activiti.engine.impl.util.json.JSONObject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
@Controller
@RequestMapping("/gt")
public class GeetestController {
/**
* 初始化极验
*
* @param request
* @param geetestDto
* @param random 防止缓存
* @return
*/
@GetMapping("/register")
@ResponseBody
protected void register(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
GeetestLib gtSdk = new GeetestLib(GeetestConfig.getGeetest_id(), GeetestConfig.getGeetest_key(),
GeetestConfig.isnewfailback());
String resStr = "{}";
String userid = "test";
//自定义参数,可选择添加
HashMap<String, String> param = new HashMap<String, String>();
param.put("user_id", userid); //网站用户id
param.put("client_type", "web"); //web:电脑上的浏览器;h5:手机上的浏览器,包括移动应用内完全内置的web_view;native:通过原生SDK植入APP应用的方式
param.put("ip_address", "127.0.0.1"); //传输用户请求验证时所携带的IP
//进行验证预处理
int gtServerStatus = gtSdk.preProcess(param);
//将服务器状态设置到session中
request.getSession().setAttribute(gtSdk.gtServerStatusSessionKey, gtServerStatus);
//将userid设置到session中
request.getSession().setAttribute("userid", userid);
resStr = gtSdk.getResponseStr();
PrintWriter out = response.getWriter();
out.println(resStr);
}
/**
* 使用post方式,返回验证结果, request表单中必须包含challenge, validate, seccode
*/
@PostMapping("/validate")
@ResponseBody
protected void validate(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");
//自定义参数,可选择添加
HashMap<String, String> param = new HashMap<String, String>();
param.put("user_id", userid); //网站用户id
param.put("client_type", "web"); //web:电脑上的浏览器;h5:手机上的浏览器,包括移动应用内完全内置的web_view;native:通过原生SDK植入APP应用的方式
param.put("ip_address", "127.0.0.1"); //传输用户请求验证时所携带的IP
int gtResult = 0;
if (gt_server_status_code == 1) {
//gt-server正常,向gt-server进行二次验证
gtResult = gtSdk.enhencedValidateRequest(challenge, validate, seccode, param);
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());
}
}
}
待建geetest的前端
需要用到gt.js
我这里用的是 geetest 的bind类型。效果:https://www.geetest.com/demo/slide-bind.html
引入gt.js
<script src="gt.js"></script>
搭建容器,我是bind的一个btn
JavaScript
<script>
var handler = function (captchaObj) {
captchaObj.onReady(function () {
$("#wait").hide();
}).onSuccess(function () {
var result = captchaObj.getValidate();
if (!result) {
return alert('请完成验证');
}
$.ajax({
url: '/gt/validate',
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') {
setTimeout(function () {
//完成后发送验证码
sendsms()
// alert('登录成功');
}, 1500);
} else if (data.status === 'fail') {
setTimeout(function () {
alert('登录失败,请完成验证');
captchaObj.reset();
}, 1500);
}
}
});
});
$("#hqyzm").click(function () {
var phone = $('#bnzf-phone').val(); //获取输入的手机号码
// $.Dialog.loading();
var reg_phone = /^0?(13[0-9]|15[012356789]|18[0123456789]|14[57]|17[678]|170[059]|14[57]|166|19[89])[0-9]{8}$/;;
if(!reg_phone.test(phone)){ //验证手机是否符合格式
layer.msg("手机号格式不正确");
return false;
}
// 调用之前先通过前端表单校验
captchaObj.verify();
})
};
$.ajax({
url: "/gt/register?t=" + (new Date()).getTime(), // 加随机数防止缓存
type: "get",
dataType: "json",
success: function (data) {
// 调用 initGeetest 进行初始化
// 参数1:配置参数
// 参数2:回调,回调的第一个参数验证码对象,之后可以使用它调用相应的接口
initGeetest({
// 以下 4 个配置参数为必须,不能缺少
gt: data.gt,
challenge: data.challenge,
offline: !data.success, // 表示用户后台检测极验服务器是否宕机
new_captcha: data.new_captcha, // 用于宕机时表示是新验证码的宕机
product: "bind", // 产品形式,包括:float,popup
width: "300px",
https: true
}, handler);
}
});
</script>
效果: