前言:
先复制一段官网介绍
产品介绍
极验「行为验证」是一项可以帮助你的网站与APP识别与拦截机器程序批量自动化操作的SaaS应用。它是由极验开发的新一代人机验证产品,它不基于传统“问题-答案”的检测模式,而是通过利用深度学习对验证过程中产生的行为数据进行高维分析,发现人机行为模式与行为特征的差异,更加精准地区分人机行为。
使用场景
使用场景网站和APP,在所有可能被机器行为攻击的场景,例如但不限于注册、登录、短信接口、查询接口、营销活动、发帖评论等等,都可以部署使用「行为验证」,来抵御机器批量操作。
网站地址:点击此处
效果图:验证模式一共分为3种
①、Bind模式
②、UnBind模式
③、一键通过模式
1、首先注册账号:https://www.geetest.com/Register (注:需审核才能登陆,可以不用注册直接拿Demo中的URL)
①、登录极验后台创建应用获取APPID和APPKEY,具体步骤可参照账号创建(后台配置前端不需要)
②、远程依赖集成:在app\build.gradle中添加依赖,如果想手动下载集成参考该链接:点击此处
//极验验证(兼容androidx)
implementation 'com.geetest.sensebot:sensebot:4.2.4'
//网络请求
implementation 'com.squareup.okhttp3:okhttp:3.12.0'
2、代码部分分为
①、请求类HttpUtils
public class HttpUtils {
private static OkHttpClient okHttpClient = new OkHttpClient();
private static String cookie = "";
private static final String GEETEST_VALIDATE = "geetest_validate";
private static final String GEETEST_SECCODE = "geetest_seccode";
private static final String GEETEST_CHALLENGE = "geetest_challenge";
/**
* get请求
*/
public static String requestGet(String urlString) {
okHttpClient.followRedirects();//不让它自动重定向
okHttpClient.followSslRedirects();//安全套接层重定向
Request request = new Request.Builder().url(urlString).build();
try {
Response response = okHttpClient.newCall(request).execute();
cookie = response.header("Set-Cookie");
return response.body().string();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
/**
* post请求
*/
public static String requestPost(String urlString, String postParam) {
okHttpClient.followRedirects();
okHttpClient.followSslRedirects();
MediaType mediaType = MediaType.parse("application/x-www-form-urlencoded");
String params = null;
try {
JSONObject jsonObject = new JSONObject(postParam);
String seccode = jsonObject.getString(GEETEST_SECCODE);
String validate = jsonObject.getString(GEETEST_VALIDATE);
String challenge = jsonObject.getString(GEETEST_CHALLENGE);
params = GEETEST_VALIDATE + "=" + validate + "&" + GEETEST_SECCODE + "=" +
seccode + "&" + GEETEST_CHALLENGE + "=" + challenge;
} catch (JSONException e) {
e.printStackTrace();
}
RequestBody requestBody = RequestBody.create(mediaType, params);
Request request = new Request
.Builder()
.post(requestBody)
.header("Cookie", TextUtils.isEmpty(cookie) ? "" : cookie)
.url(urlString)
.build();
try {
Response response = okHttpClient.newCall(request).execute();
return response.body().string();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
②、配置类GeetestUtils
public class GeetestUtils {
/**
* api1,需替换成自己的服务器URL
*/
private static final String bindCaptchaURL = "https://www.geetest.com/demo/gt/register-slide";
private static final String unBindCaptchaURL = "https://www.geetest.com/demo/gt/register-click";
private static final String OnePassCaptchaURL = "https://www.geetest.com/demo/gt/register-fullpage";
/**
* api2,需替换成自己的服务器URL
*/
private static final String bindValidateURL = "https://www.geetest.com/demo/gt/validate-slide";
private static final String unBindValidateURL = "https://www.geetest.com/demo/gt/validate-click";
private static final String OnePassValidateURL = "https://www.geetest.com/demo/gt/validate-fullpage";
private static GT3GeetestUtils mGt3GeetestUtils;
private static GT3ConfigBean gt3ConfigBean;
private static final String TAG = "GeetestUtils";
private static String rquestCaptchaUrl, rquestValidateUrl;
/**
* 0 绑定 1 非绑定 2 一键通过
*
* @param activity 上下文
* @param button 按钮
* @param type 类型
*/
public static void customVerity(Activity activity, GT3GeetestButton button, int type) {
if (type == 1) {
rquestCaptchaUrl = bindCaptchaURL;
rquestValidateUrl = bindValidateURL;
} else if (type == 2) {
rquestCaptchaUrl = unBindCaptchaURL;
rquestValidateUrl = unBindValidateURL;
} else if (type == 3) {
rquestCaptchaUrl = OnePassCaptchaURL;
rquestValidateUrl = OnePassValidateURL;
}
// TODO 请在oncreate方法里初始化以获取足够手势数据来保证第一轮验证成功率
mGt3GeetestUtils = new GT3GeetestUtils(activity);
// 配置bean文件,也可在oncreate初始化
gt3ConfigBean = new GT3ConfigBean();
// 设置验证模式,1:bind,2:unbind
int pattern = type == 3 ? type - 1 : type;//type等于3-1 type=2
gt3ConfigBean.setPattern(pattern);
// 设置点击灰色区域是否消失,默认不消失
gt3ConfigBean.setCanceledOnTouchOutside(false);
// 设置语言,如果为null则使用系统默认语言中文(TODO 若想设置语言立即生效,则init需要在setContentView之前)
// String language ="zh";
// String language ="en";
// String language ="ja";
// String language = "zh";
// gt3ConfigBean.setLang(language);
// 设置加载webview超时时间,单位毫秒,默认10000,仅且webview加载静态文件超时,不包括之前的http请求
gt3ConfigBean.setTimeout(30000);
// 设置webview请求超时(用户点选或滑动完成,前端请求后端接口),单位毫秒,默认10000
gt3ConfigBean.setWebviewTimeout(30000);
// 设置回调监听
gt3ConfigBean.setListener(new GT3Listener() {
/**
* 验证码加载完成
* @param duration 加载时间和版本等信息,为json格式
*/
@Override
public void onDialogReady(String duration) {
Log.e(TAG, "GT3BaseListener-->onDialogReady-->" + duration);
}
/**
* 图形验证结果回调
* @param code 1为正常 0为失败
*/
@Override
public void onReceiveCaptchaCode(int code) {
Log.e(TAG, "GT3BaseListener-->onReceiveCaptchaCode-->" + code);
}
/**
* 自定义api2回调
* @param result,api2请求上传参数
*/
@Override
public void onDialogResult(String result) {
Log.e(TAG, "GT3BaseListener-->onDialogResult-->" + result);
// 开启api2逻辑
new RequestAPI2().execute(result);
}
/**
* 统计信息,参考接入文档
* @param result
*/
@Override
public void onStatistics(String result) {
Log.e(TAG, "GT3BaseListener-->onStatistics-->" + result);
}
/**
* 验证码被关闭
* @param num 1 点击验证码的关闭按钮来关闭验证码, 2 点击屏幕关闭验证码, 3 点击返回键关闭验证码
*/
@Override
public void onClosed(int num) {
Log.e(TAG, "GT3BaseListener-->onClosed-->" + num);
}
/**
* 验证成功回调
* @param result
*/
@Override
public void onSuccess(String result) {
Log.e(TAG, "GT3BaseListener-->onSuccess-->" + result);
}
/**
* 验证失败回调
* @param errorBean 版本号,错误码,错误描述等信息
*/
@Override
public void onFailed(GT3ErrorBean errorBean) {
Log.e(TAG, "GT3BaseListener-->onFailed-->" + errorBean.toString());
}
/**
* 自定义api1回调
*/
@Override
public void onButtonClick() {
new RequestAPI1().execute();
}
});
mGt3GeetestUtils.init(gt3ConfigBean);
if (type == 1) {
// 开启验证
mGt3GeetestUtils.startCustomFlow();
} else {
button.setGeetestUtils(mGt3GeetestUtils);
}
}
/**
* 请求api1
*/
static class RequestAPI1 extends AsyncTask<Void, Void, JSONObject> {
@Override
protected JSONObject doInBackground(Void... params) {
// TODO 添加时间戳防止请求被缓存
String string = HttpUtils.requestGet(rquestCaptchaUrl + "?t=" + System.currentTimeMillis());
JSONObject jsonObject = null;
try {
jsonObject = new JSONObject(string);
} catch (Exception e) {
e.printStackTrace();
}
return jsonObject;
}
@Override
protected void onPostExecute(JSONObject parmas) {
// 继续验证
Log.i(TAG, "RequestAPI1-->onPostExecute: " + parmas);
// SDK可识别格式为
// {"success":1,"challenge":"06fbb267def3c3c9530d62aa2d56d018",
// "gt":"019924a82c70bb123aae90d483087f94"}
// 设置返回api1数据
// TODO 将api1请求结果传入此方法,即使为null也要传入,SDK内部已处理
gt3ConfigBean.setApi1Json(parmas);
mGt3GeetestUtils.getGeetest();
}
}
/**
* 请求api2
*/
static class RequestAPI2 extends AsyncTask<String, Void, String> {
@Override
protected String doInBackground(String... params) {
if (!TextUtils.isEmpty(params[0])) {
return HttpUtils.requestPost(rquestValidateUrl, params[0]);
} else {
return null;
}
}
@Override
protected void onPostExecute(String result) {
Log.i(TAG, "RequestAPI2-->onPostExecute: " + result);
if (!TextUtils.isEmpty(result)) {
try {
JSONObject jsonObject = new JSONObject(result);
String status = jsonObject.optString("status");
if (TextUtils.isEmpty(status)) {
status = jsonObject.optString("result");
}
if ("success".equals(status)) {
mGt3GeetestUtils.showSuccessDialog();
} else {
mGt3GeetestUtils.showFailedDialog();
}
} catch (Exception e) {
mGt3GeetestUtils.showFailedDialog();
e.printStackTrace();
}
} else {
mGt3GeetestUtils.showFailedDialog();
}
}
}
/**
* 页面关闭时释放资源
*/
public static void onDestroy() {
if (mGt3GeetestUtils != null) {
mGt3GeetestUtils.destory();
mGt3GeetestUtils = null;
}
}
/**
* 界面切换
*/
public static void changeDialogLayout(Configuration configuration) {
/**
* 设置后,界面横竖屏不会关闭验证码,推荐设置
*/
if (mGt3GeetestUtils != null) {
mGt3GeetestUtils.changeDialogLayout();
}
}
}
③、使用类GeetestActivity
public class GeetestActivity extends AppCompatActivity {
private final String TAG = "GeetestUtils";
private GT3GeetestButton geetestBtn;
private Button btnBind, changeBtn;
//默认模式(false 一键通过 true UNBind模式)
private boolean defaultModel;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_geetest);
geetestBtn = this.findViewById(R.id.geetest);
changeBtn = this.findViewById(R.id.change_btn);
//绑定模式
this.findViewById(R.id.bind).setOnClickListener(v -> {
GeetestUtils.customVerity(this, null, 1);
});
changeBtn.setOnClickListener(v -> {
if (defaultModel) {
defaultModel = false;
} else {
defaultModel = true;
}
setGeetestModel();
});
setGeetestModel();
}
/**
* 设置moshi
*/
private void setGeetestModel() {
if (defaultModel) {
//UNBind模式
GeetestUtils.customVerity(this, geetestBtn, 2);
changeBtn.setText("UNBind模式 《点击此处》");
} else {
//一键通过模式
GeetestUtils.customVerity(this, geetestBtn, 3);
changeBtn.setText("一键通过模式 《点击此处》");
}
}
/**
* 界面关闭时释放资源
*/
@Override
protected void onDestroy() {
super.onDestroy();
GeetestUtils.onDestroy();
}
/**
* 横竖屏切换
* 界面横竖屏不会关闭验证码,推荐设置
*/
@Override
public void onConfigurationChanged(@NonNull Configuration newConfig) {
super.onConfigurationChanged(newConfig);
GeetestUtils.changeDialogLayout(newConfig);
}
}
布局文件就是两个基本的Button和一个SDK的按钮
<com.geetest.sdk.views.GT3GeetestButton
android:id="@+id/btn_geetest"
android:layout_width="300dp"
android:layout_height="45dp" />
注意:清单文件添加Intent网络权限这里就不贴出代码了!