geetest滑动验证

最近公司为了安全,在登录注册,发送短信等需要验证的地方改为用滑动验证,再此记录一下

一、注册账号极验官网
进去以后找到

ID和key值需要记住,代码中需要配置
二、下载demo,我用的是java
主要代码如下:代码中都有注释,就不做详细介绍

/*** 配置文件,可合理选择properties等方式自行设计*/
public class GeetestConfig {/*** 填入自己在极验官网申请的账号id和key*/public static final String GEETEST_ID = "";public static final String GEETEST_KEY = "";}
package com.persional.controller.geetest;import org.json.JSONObject;import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.util.Iterator;
import java.util.Map;
import java.util.UUID;/*** sdk lib包,核心逻辑。** @author*/
public class GeetestLib {/*** 公钥*/private String geetest_id;/*** 私钥*/private String geetest_key;/*** 返回数据的封装对象*/private GeetestLibResult libResult;/*** 调试开关,是否输出调试日志*/private static final boolean IS_DEBUG = true;private static final String API_URL = "http://api.geetest.com";private static final String REGISTER_URL = "/register.php";private static final String VALIDATE_URL = "/validate.php";private static final String JSON_FORMAT = "1";private static final boolean NEW_CAPTCHA = true;public static final String VERSION = "jave-servlet-maven:3.1.0";/*** 极验二次验证表单传参字段 chllenge*/public static final String GEETEST_CHALLENGE = "geetest_challenge";/*** 极验二次验证表单传参字段 validate*/public static final String GEETEST_VALIDATE = "geetest_validate";/*** 极验二次验证表单传参字段 seccode*/public static final String GEETEST_SECCODE = "geetest_seccode";/*** 极验验证API服务状态Session Key*/public static final String GEETEST_SERVER_STATUS_SESSION_KEY = "gt_server_status";public GeetestLib(String geetest_id, String geetest_key) {this.geetest_id = geetest_id;this.geetest_key = geetest_key;this.libResult = new GeetestLibResult();}public void gtlog(String message) {if (this.IS_DEBUG) {System.out.println("gtlog: " + message);}}/*** 一次验证*/public GeetestLibResult register(String digestmod, Map<String, String> paramMap,String userId) {this.gtlog(String.format("register(): 开始一次验证, digestmod=%s.", digestmod));String origin_challenge = requestRegister(paramMap);buildRegisterResult(origin_challenge, digestmod,userId);this.gtlog(String.format("register(): 一次验证, lib包返回信息=%s.", this.libResult));return this.libResult;}/*** 向极验发送一次验证的请求,GET方式*/private String requestRegister(Map<String, String> paramMap) {paramMap.put("gt", this.geetest_id);paramMap.put("json_format", this.JSON_FORMAT);String register_url = this.API_URL + this.REGISTER_URL;this.gtlog(String.format("requestRegister(): 一次验证, 向极验发送请求, url=%s, params=%s.", register_url, paramMap));String origin_challenge = null;try {String resBody = this.httpGet(register_url, paramMap);this.gtlog(String.format("requestRegister(): 一次验证, 与极验网络交互正常, 返回body=%s.", resBody));JSONObject jsonObject = new JSONObject(resBody);origin_challenge = jsonObject.getString("challenge");} catch (Exception e) {this.gtlog("requestRegister(): 一次验证, 请求异常,后续流程走failback模式, " + e.toString());origin_challenge = "";}return origin_challenge;}/*** 构建一次验证返回数据*/private void buildRegisterResult(String origin_challenge, String digestmod,String userId) {// origin_challenge为空或者值为0代表失败if (origin_challenge == null || origin_challenge.isEmpty() || "0".equals(origin_challenge)) {// 本地随机生成32位字符串String challenge = UUID.randomUUID().toString().replaceAll("-", "");JSONObject jsonObject = new JSONObject();jsonObject.put("success", 0);jsonObject.put("gt", this.geetest_id);jsonObject.put("challenge", challenge);jsonObject.put("userId", userId);jsonObject.put("new_captcha", this.NEW_CAPTCHA);this.libResult.setAll(0, jsonObject.toString(), "请求极验register接口失败,后续流程走failback模式");} else {String challenge = null;if ("md5".equals(digestmod)) {challenge = this.md5_encode(origin_challenge + this.geetest_key);} else if ("sha256".equals(digestmod)) {challenge = this.sha256_encode(origin_challenge + this.geetest_key);} else if ("hmac-sha256".equals(digestmod)) {challenge = this.hmac_sha256_encode(origin_challenge, this.geetest_key);} else {challenge = this.md5_encode(origin_challenge + this.geetest_key);}JSONObject jsonObject = new JSONObject();jsonObject.put("success", 1);jsonObject.put("gt", this.geetest_id);jsonObject.put("challenge", challenge);jsonObject.put("userId", userId);jsonObject.put("new_captcha", this.NEW_CAPTCHA);this.libResult.setAll(1, jsonObject.toString(), "");}}/*** 正常流程下(即一次验证请求成功),二次验证*/public GeetestLibResult successValidate(String challenge, String validate, String seccode, Map<String, String> paramMap) {this.gtlog(String.format("successValidate(): 开始二次验证 正常模式, challenge=%s, validate=%s, seccode=%s.", challenge, validate, seccode));if (!check_param(challenge, validate, seccode)) {this.libResult.setAll(0, "", "正常模式,本地校验,参数challenge、validate、seccode不可为空");} else {String response_seccode = this.requestValidate(challenge, validate, seccode, paramMap);if (response_seccode == null || response_seccode.isEmpty()) {this.libResult.setAll(0, "", "请求极验validate接口失败");} else if ("false".equals(response_seccode)) {this.libResult.setAll(0, "", "极验二次验证不通过");} else {this.libResult.setAll(1, "", "");}}this.gtlog(String.format("successValidate(): 二次验证 正常模式, lib包返回信息=%s.", this.libResult));return this.libResult;}/*** 异常流程下(即failback模式),二次验证* 注意:由于是failback模式,初衷是保证验证业务不会中断正常业务,所以此处只作简单的参数校验,可自行设计逻辑。*/public GeetestLibResult failValidate(String challenge, String validate, String seccode) {this.gtlog(String.format("failValidate(): 开始二次验证 failback模式, challenge=%s, validate=%s, seccode=%s.", challenge, validate, seccode));if (!this.check_param(challenge, validate, seccode)) {this.libResult.setAll(0, "", "failback模式,本地校验,参数challenge、validate、seccode不可为空.");} else {this.libResult.setAll(1, "", "");}this.gtlog(String.format("failValidate(): 二次验证 failback模式, lib包返回信息=%s.", this.libResult));return this.libResult;}/*** 向极验发送二次验证的请求,POST方式*/private String requestValidate(String challenge, String validate, String seccode, Map<String, String> paramMap) {paramMap.put("seccode", seccode);paramMap.put("json_format", this.JSON_FORMAT);paramMap.put("challenge", challenge);paramMap.put("sdk", this.VERSION);paramMap.put("captchaid", this.geetest_id);String validate_url = this.API_URL + this.VALIDATE_URL;this.gtlog(String.format("requestValidate(): 二次验证 正常模式, 向极验发送请求, url=%s, params=%s.", validate_url, paramMap));String response_seccode = null;try {String resBody = this.httpPost(validate_url, paramMap);this.gtlog(String.format("requestValidate(): 二次验证 正常模式, 与极验网络交互正常, 返回body=%s.", resBody));JSONObject jsonObject = new JSONObject(resBody);response_seccode = jsonObject.getString("seccode");} catch (Exception e) {this.gtlog(String.format("requestValidate(): 二次验证 正常模式, 请求异常, " + e.toString()));response_seccode = "";}return response_seccode;}/*** 校验二次验证的三个参数,校验通过返回true,校验失败返回false*/private boolean check_param(String challenge, String validate, String seccode) {if (challenge == null || challenge.isEmpty() || validate == null || validate.isEmpty() || seccode == null || seccode.isEmpty()) {return false;}return true;}/*** 发送GET请求,获取服务器返回结果*/private String httpGet(String url, Map<String, String> paramMap) throws Exception {Iterator<String> it = paramMap.keySet().iterator();StringBuilder paramStr = new StringBuilder();while (it.hasNext()) {String key = it.next();if (key == null || key.isEmpty() || paramMap.get(key) == null || paramMap.get(key).isEmpty()) {continue;}paramStr.append("&").append(URLEncoder.encode(key, "utf-8")).append("=").append(URLEncoder.encode(paramMap.get(key), "utf-8"));}if (paramStr.length() != 0) {paramStr.replace(0, 1, "?");}url += paramStr.toString();URL getUrl = new URL(url);HttpURLConnection connection = (HttpURLConnection) getUrl.openConnection();connection.setConnectTimeout(2000); // 设置连接主机超时(单位:毫秒)connection.setReadTimeout(2000); // 设置从主机读取数据超时(单位:毫秒)connection.connect();if (connection.getResponseCode() == 200) {StringBuilder sb = new StringBuilder();InputStream inStream = null;byte[] buf = new byte[1024];inStream = connection.getInputStream();for (int n; (n = inStream.read(buf)) != -1; ) {sb.append(new String(buf, 0, n, "UTF-8"));}inStream.close();connection.disconnect();return sb.toString();}return "";}/*** 发送POST请求,获取服务器返回结果*/private String httpPost(String url, Map<String, String> paramMap) throws Exception {Iterator<String> it = paramMap.keySet().iterator();StringBuilder paramStr = new StringBuilder();while (it.hasNext()) {String key = it.next();if (key == null || key.isEmpty() || paramMap.get(key) == null || paramMap.get(key).isEmpty()) {continue;}paramStr.append("&").append(URLEncoder.encode(key, "utf-8")).append("=").append(URLEncoder.encode(paramMap.get(key), "utf-8"));}if (paramStr.length() != 0) {paramStr.replace(0, 1, "");}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(paramStr.toString());outputStreamWriter.flush();outputStreamWriter.close();if (connection.getResponseCode() == 200) {StringBuilder sb = new StringBuilder();InputStream inStream = null;byte[] buf = new byte[1024];inStream = connection.getInputStream();for (int n; (n = inStream.read(buf)) != -1; ) {sb.append(new String(buf, 0, n, "UTF-8"));}inStream.close();connection.disconnect();return sb.toString();}return "";}/*** md5 加密*/private String md5_encode(String plainText) {String re_md5 = new String();try {MessageDigest md = MessageDigest.getInstance("MD5");md.update(plainText.getBytes());byte b[] = md.digest();int i;StringBuilder sb = new StringBuilder("");for (int offset = 0; offset < b.length; offset++) {i = b[offset];if (i < 0) {i += 256;}if (i < 16) {sb.append("0");}sb.append(Integer.toHexString(i));}re_md5 = sb.toString();} catch (Exception e) {this.gtlog("md5_encode(): 发生异常, " + e.toString());}return re_md5;}/*** sha256加密*/public String sha256_encode(String plainText) {MessageDigest messageDigest;String encodeStr = new String();try {messageDigest = MessageDigest.getInstance("SHA-256");messageDigest.update(plainText.getBytes("UTF-8"));encodeStr = byte2Hex(messageDigest.digest());} catch (Exception e) {this.gtlog("sha256_encode(): 发生异常, " + e.toString());}return encodeStr;}/*** 将byte转为16进制*/private static String byte2Hex(byte[] bytes) {StringBuilder sb = new StringBuilder();String temp = null;for (int i = 0; i < bytes.length; i++) {temp = Integer.toHexString(bytes[i] & 0xFF);if (temp.length() == 1) {// 得到一位的进行补0操作sb.append("0");}sb.append(temp);}return sb.toString();}/*** hmac-sha256 加密*/private String hmac_sha256_encode(String data, String key) {String encodeStr = new String();try {Mac sha256_HMAC = Mac.getInstance("HmacSHA256");SecretKeySpec secret_key = new SecretKeySpec(key.getBytes("UTF-8"), "HmacSHA256");sha256_HMAC.init(secret_key);byte[] array = sha256_HMAC.doFinal(data.getBytes("UTF-8"));StringBuilder sb = new StringBuilder();for (byte item : array) {sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3));}encodeStr = sb.toString();} catch (Exception e) {this.gtlog("hmac_sha256_encode(): 发生异常, " + e.toString());}return encodeStr;}}
/*** sdk lib包的返回结果信息。** @author*/
public class GeetestLibResult {/*** 成功失败的标识码,1表示成功,0表示失败*/private int status = 0;/*** 返回数据,json格式*/private String data = "";/*** 备注信息,如异常信息等*/private String msg = "";public void setStatus(int status) {this.status = status;}public int getStatus() {return status;}public void setData(String data) {this.data = data;}public String getData() {return data;}public void setMsg(String msg) {this.msg = msg;}public String getMsg() {return msg;}public void setAll(int status, String data, String msg) {this.setStatus(status);this.setData(data);this.setMsg(msg);}@Overridepublic String toString() {return String.format("GeetestLibResult{status=%s, data=%s, msg=%s}", this.status, this.data, this.msg);}
}
import com.persional.controller.geetest.GeetestConfig;
import com.persional.controller.geetest.GeetestLib;
import com.persional.controller.geetest.GeetestLibResult;
import com.persional.jwt.PassToken;
import com.persional.util.RedisUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
/*** @Auther fzc* @Date 2021/7/2*/
public class GeetestController {@Autowiredprivate RedisUtil redisUtil;/*** @description* 第一次验证,进页面则去调用* @return:* @authon: fzc* @date: 2021/7/2 下午4:13*/public void StartCaptcha(HttpServletRequest request,HttpServletResponse response) throws IOException {GeetestLib gtLib = new GeetestLib(GeetestConfig.GEETEST_ID,GeetestConfig.GEETEST_KEY);//自定义参数,可选择添加String userId=UUID.randomUUID().toString();HashMap<String, String> paramMap = new HashMap<String, String>();//网站用户idparamMap.put("user_id", userId);//web:电脑上的浏览器;h5:手机上的浏览器,包括移动应用内完全内置的web_view;native:通过原生SDK植入APP应用的方式paramMap.put("client_type", "web");//传输用户请求验证时所携带的IPparamMap.put("ip_address", "127.0.0.1");// 进行一次验证,得到结果GeetestLibResult result = gtLib.register("",paramMap,userId);// 把生成的userId和第一次验证返回的状态放到redis中,第二次验证需要取用redisUtil.set(userId,result.getStatus());// 注意,此处api1接口存入session,api2会取出使用,格外注意session的存取和分布式环境下的应用场景PrintWriter out = response.getWriter();// 注意,不要更改返回的结构和值类型,会报错,如果想添加参数,可以去修改第一次验证返回的数据out.println(result.getData());}/*** @description* 第二次验证,参数为* geetest_challenge* geetest_validate* geetest_seccode* @return:* @authon: fzc* @date: 2021/7/2 下午4:13*/public void verifyLogin(Map<String, Object> params,HttpServletResponse response) throws IOException {System.out.println("params++"+params);GeetestLib gtLib = new GeetestLib(GeetestConfig.GEETEST_ID,GeetestConfig.GEETEST_KEY);String challenge = String.valueOf(params.get("geetest_challenge"));String validate = String.valueOf(params.get("geetest_validate"));String seccode = String.valueOf(params.get("geetest_seccode"));String userId = String.valueOf(params.get("userId"));PrintWriter out = response.getWriter();int gt_server_status_code = 0;try {System.out.println("userId++++"+userId);System.out.println("seccode++++"+seccode);gt_server_status_code = (int) redisUtil.get(userId);System.out.println("gt_server_status_code+++"+gt_server_status_code);} catch (Exception e) {gtLib.gtlog("SecondValidateServlet.doPost():二次验证validate:session取key发生异常,"+ e.toString());out.println("{\"status\":\"fail\"}");return;}//自定义参数,可选择添加HashMap<String, String> param = new HashMap<String, String>();//网站用户idparam.put("user_id", userId);GeetestLibResult result = null;// gt_server_status_code 为1代表一次验证register正常,走正常二次验证模式;为0代表一次验证异常,走failback模式if (gt_server_status_code == 1) {//gt-server正常,向极验服务器发起二次验证result = gtLib.successValidate(challenge, validate, seccode, param);} else {// gt-server非正常情况,进行failback模式本地验证result = gtLib.failValidate(challenge, validate, seccode);}// // 注意,不要更改返回的结构和值类型out.println(result.getStatus());}
}

spring boot+ geetest滑动验证相关推荐

  1. spring boot 登录滑动验证

    1.配置pom.xml坐标 cloud.tianai.captcha 2.配置Listener package com.lw.utils;import cloud.tianai.captcha.sli ...

  2. Spring Boot 极验验证滑动验证码

    概要 基于极验验证官网 java版gt3-java-sdk改编,使用Spring Boot 整合的极验滑动验证,包含form表单登录和ajax登录两种情况. 目录 注册账户获取ID和KEY Demo源 ...

  3. Spring Boot SSL证书验证的问题

    在Spring Boot应用用启动时调用: private static void disableSslVerification() {try {SSLContext sslcontext = SSL ...

  4. Spring Boot实现注册验证全过程

    0. 阅读完本文你将会学会 如何实现一个基本的注册验证过程 如何自定义一个注解 1. 概述 在这篇文章中,我们将使用Spring Boot实现一个基本的邮箱注册账户以及验证的过程. 我们的目标是添加一 ...

  5. Spring Boot validator参数验证restful自定义错误码响应

    2019独角兽企业重金招聘Python工程师标准>>> 关于spring web应用中关于如何使用 Bean Validation API和hibernate-validator的文 ...

  6. Spring boot短信验证登录

    一.短信验证码业务 我用的是第三平台的短信服务,当用户点击发送验证码,会调用短信平台接口,从而给手机发验证码.流程如下: c 首先需要工具类,来发送验证码 public class DXMessage ...

  7. Spring Boot 表单验证

    1.对实体类属性的注解例子如下:

  8. Python Selenium 破解极验(GeeTest)滑动验证

    ArmourGeeTestArmourGeeTestArmourGeeTest [TOS] 本项目仅供交流学习,有疑问请在issue中提出: 本项目不提供面向任何商业需求的版本迭代: 关于本项目源码的 ...

  9. 在Spring Boot中进行验证Bean

最新文章

  1. 第10章 图与网络优化
  2. Debian 编译内核全过程[转]
  3. Windows中启动Redis走配置文件的bat脚本
  4. Android自动化测试 - 自动化测试工具比较
  5. html 鼠标图标做成动画效果,纯css3实现的鼠标悬停动画按钮
  6. sentinel 端口_Sentinel原理:控制台是如何获取到实时数据的
  7. Linux下查看端口状态的小工具lsof
  8. python flask文件下载 | 实用代码架构
  9. 二维码批量生成系统 windows的exe 程序执行 二维码工具 解压直接使用
  10. C语言定时器按键消抖程序,按键消抖方法(中断与定时器配合使用)
  11. PDF不能编辑怎么办?捷速PDF编辑器快速编辑!
  12. 91 卫图与bigemap地图下载器功能对比
  13. VC编程--玩转控件(Windows编程简介)
  14. word上下的横线怎么去掉_word中去掉页面上的横线 word页面横线怎么去掉
  15. MATLAB 提取图片曲线
  16. [计算机网络]交换机环路问题
  17. 使用Phaser开发你的第一个H5游戏(一)
  18. android 设备驱动
  19. 精力管理-健康生活 高效工作
  20. sql 纵表横表转换

热门文章

  1. sunday算法特征码_sunday 算法
  2. ARM开发---基础认识
  3. 复变函数与积分变换系列(一) - 复变函数与解析函数
  4. 【网络通信 -- 直播】项目实战记录 -- 弱网模拟工具
  5. 《时生》BY东野圭吾
  6. 定做加工菠萝格凉亭材料需要哪些工序
  7. 安装客户端报错:“错误:-1628 基于脚本的安装失败。”
  8. RZ7899电机驱动
  9. 如何开启小米手机5的ROOT权限
  10. 基于php的同学校友录网站