【集成】极验验证
来源:互联网 发布:连汝安 知乎 编辑:程序博客网 时间:2024/04/28 18:04
极验验证
极验验证地址
http://www.geetest.com
极验验证用途
防止用户恶意频繁请求服务器,也就是防刷,主要用于安全认证。
看官方文档你会发现,其实就是通过弹出验证码窗口进行验证拦截,根据验证结果你可进行自己的操作。
极验验证的使用集成
此处在官方文档有说明,详情点击http://docs.geetest.com/install/client/android/,此处不做赘述。
在此主要说出集成极验验证时的一些坑,以及处理方案。
基本说明:需要服务器提供两个接口 初始化配置接口/验证接口
进入源码你会发现sdk通过
new GT3GeetestUrl().setCaptchaURL(captchaURL);new GT3GeetestUrl().setValidateURL(validateURL);
将初始化接口/验证接口进行了保存(请自行查看源码),之后通过
gt3GeetestUtils.getGeetest();
进行开始验证,在此通过执行task来对之前配置的两个接口发起网络请求,那么问题来了
1.如何在请求中插入cookie
/** * 验证回调 */ private static class GTListener implements GT3GeetestUtils.GT3Listener { private Map<String, String> data = new HashMap<>(); // dialog关闭 @Override public void gt3CloseDialog() { isCloseFlag = true; } // 点击其他,关闭dialog @Override public void gt3CancelDialog() { isCloseFlag = true; } // 验证码加载准备完成 @Override public void gt3DialogReady() { EvtLog.e("validate", "gt3DialogReady"); } // 首次请求返回结果,将getCode拿到的两个数据,在发送验证的时候带回去 // 因为sdk不支持添加cookie,所以用此方法来通知后台是否为同一用户 @Override public void gt3FirstResult(JSONObject jsonObject) { try { data.put("captcha_uid", jsonObject.getString("captcha_uid")); data.put("status", jsonObject.getString("status")); } catch (JSONException e) { e.printStackTrace(); } } // 二次请求返回结果 @Override public Map<String, String> gt3SecondResult() { return data; } @Override public void gt3GetDialogResult(String result) { } // 验证码 验证成功 @Override public void gt3DialogSuccess() { isCloseFlag = true; } // 验证码 验证失败 @Override public void gt3DialogOnError() { isCloseFlag = true; } @Override public void gt3DialogSuccessResult(String result) { } @Override public Map<String, String> captchaHeaders() { // 此方法只是将cookie相关数据加到header并没有加到cookie,依然会造成后台生成新的seesionid // 处理方案,后台返回一个唯一标识,在验证时返回 回去// LZCookieStore cookieStore = new LZCookieStore(FeizaoApp.mConctext);// List<Cookie> cookies = cookieStore.getCookies();// Map<String, String> data = new HashMap<>();// if (cookies != null) {// for (Cookie cookie :// cookies) {// data.put(cookie.getName(), cookie.getValue());// }// }// return data; return null; } }
在sdk提供的回调中captchaHeaders()是给 初始化配置接口请求时添加header,但是并未单独放入cookie下面,所以需要自己解析。
但实际应用场景一般会在cookie下面放入一些参数用于判断是否为同一用户下的请求,所以在这里有两个解决方案
1. 后台在此接口上做特殊判断,在header中直接去拿,我们通过captchaHeaders()将参数放入header;
2. 我们初始化请求时服务器返回一个参数作为唯一标识,在验证validate的接口时,将此参数值带入到请求body中。
在此段代码中,也就是我当前的项目中使用的是第二种方式进行的处理
2.如何避免谈起多个dialog
sdk通过geetestUtils.getGeetest();
来开启验证的,那么我们看一下它的源码
public void getGeetest() { getLight = GT3LifecycleCallBacks.getInstance(context).gt3SendMsg(); GT3LifecycleCallBacks.getInstance(context).clearAllMsg(); senMsg = new GT3AroundMsg(context).gt3SendSenMsg(); new GT3AroundMsg(context).endSensor(); mGtAppDlgTask = new GtAppDlgTask(); mGtAppDlgTask.execute(); if (!((Activity) context).isFinishing()) { dialog = new GT3GtDialog(context); Window dialogWindow = dialog.getWindow(); WindowManager.LayoutParams lp = dialogWindow.getAttributes(); dialogWindow.setGravity(Gravity.CENTER); dialogWindow.setAttributes(lp); dialog.show(); dialog.setOnCancelListener(new DialogInterface.OnCancelListener() { @Override public void onCancel(DialogInterface dialo) { gtListener.gt3CancelDialog(); } }); dialog.setGtListener(new GT3GtDialog.GtListener() { @Override public void gtResult(boolean success, String result) { gtListener.gt3GetDialogResult(result); if (success) { mGtAppValidateTask = new GtAppValidateTask(); mGtAppValidateTask.execute(result); } else { //TODO 验证失败 dialog.shakeDialog(); } } @Override public void success() { gtListener.gt3DialogSuccess(); } @Override public void gtCallReady(Boolean status) { if (status) { //TODO 验证加载完成 gtListener.gt3DialogReady(); } else { //TODO 验证加载超时,未准备完成 } } @Override public void gtCallClose() { gtListener.gt3CloseDialog(); } @Override public void gtError() { gtListener.gt3DialogOnError(); } }); } captcha.setTimeout(5000); captcha.setGeetestListener(new GT3Geetest.GeetestListener() { @Override public void readContentTimeout() { mGtAppDlgTask.cancel(true); //TODO 获取验证参数超时 //Looper.prepare() & Looper.loop(): 在当前线程并没有绑定Looper时返回为null, 可以与toastMsg()一同在正式版本移除 Looper.prepare();// toastMsg("read content time out"); Looper.loop(); } @Override public void submitPostDataTimeout() { mGtAppValidateTask.cancel(true); //TODO 提交二次验证超时// toastMsg("submit error"); } @Override public void receiveInvalidParameters() { //TODO 从API接收到无效的JSON参数// toastMsg("Did recieve invalid parameters."); } }); }
观察源码你会发现,
1. 只要当前activity未停止,只要你调用此方法就会打开新的dialog,并且sdk未提供dialog手动销毁的方法。所以在此你会遇到的问题是:当你请求多个接口并且都需要验证时,它会谈起多个对话框,影响用户体验。在此我做了一个处理,代码如下:
package packagename.common;import android.app.Activity;import com.efeizao.feizao.library.util.EvtLog;import com.example.sdk.GT3GeetestUtils;import org.json.JSONException;import org.json.JSONObject;import java.lang.ref.WeakReference;import java.util.HashMap;import java.util.Map;/** * Created by Elvis on 2017/6/21. * description : 使用极验验证请求,操作是否频繁,存在自动刷请求 */public class GTValidateRequest { private static GT3GeetestUtils geetestUtils = null; private static GTValidateRequest gtValidateRequest = null; private static boolean isCloseFlag = true; //如果dialog被关闭则为true,否则为false public static GTValidateRequest getInstance() { if (gtValidateRequest == null) { gtValidateRequest = new GTValidateRequest(); } return gtValidateRequest; } /** * @param context 上下文activity,用于第三方sdk使用(第三方仅支持activity作为上下文对象) */ public void validate(WeakReference<Activity> context) { EvtLog.e("validate", "activity:" + context.get().getComponentName().getClassName()); // dialog已经关闭 if (isCloseFlag) { isCloseFlag = false; if (geetestUtils == null) { geetestUtils = new GT3GeetestUtils(context.get()); } geetestUtils.setGtListener(new GTListener()); geetestUtils.getGeetest(); } } /** * 验证回调 */ private static class GTListener implements GT3GeetestUtils.GT3Listener { private Map<String, String> data = new HashMap<>(); // dialog关闭 @Override public void gt3CloseDialog() { isCloseFlag = true; } // 点击其他,关闭dialog @Override public void gt3CancelDialog() { isCloseFlag = true; } // 验证码加载准备完成 @Override public void gt3DialogReady() { EvtLog.e("validate", "gt3DialogReady"); } // 首次请求返回结果,将getCode拿到的两个数据,在发送验证的时候带回去 // 因为sdk不支持添加cookie,所以用此方法来通知后台是否为同一用户 @Override public void gt3FirstResult(JSONObject jsonObject) { try { data.put("captcha_uid", jsonObject.getString("captcha_uid")); data.put("status", jsonObject.getString("status")); } catch (JSONException e) { e.printStackTrace(); } } // 二次请求返回结果 @Override public Map<String, String> gt3SecondResult() { return data; } @Override public void gt3GetDialogResult(String result) { } // 验证码 验证成功 @Override public void gt3DialogSuccess() { isCloseFlag = true; } // 验证码 验证失败 @Override public void gt3DialogOnError() { isCloseFlag = true; } @Override public void gt3DialogSuccessResult(String result) { } @Override public Map<String, String> captchaHeaders() { // 此方法只是将cookie相关数据加到header并没有加到cookie,依然会造成后台生成新的seesionid // 处理方案,后台返回一个唯一标识,在验证时返回 回去// LZCookieStore cookieStore = new LZCookieStore(FeizaoApp.mConctext);// List<Cookie> cookies = cookieStore.getCookies();// Map<String, String> data = new HashMap<>();// if (cookies != null) {// for (Cookie cookie :// cookies) {// data.put(cookie.getName(), cookie.getValue());// }// }// return data; return null; } }}
在代码中我添加了一个boolean作为标识,用来判断dialog是否被关闭。
默认为关闭,也就是默认允许弹出dialog,当弹出后,状态设置为false,说明已经打开dialog;然后在它的监听中设置状态,gt3CloseDialog()/gt3CancelDialog()/gt3DialogSuccess()/gt3DialogOnError(),这几中情况dialog都会被关闭,我们在此将状态设置为true。这样就可以用来避免dialog的多次打开。(此方案之适用于之前dialog依赖的activity已经销毁。当activity销毁时,dialog也会销毁。如果存在未销毁情况,你只需要在此方案上加入activity是否为同一个的判断就好)。
3. 初始化GT3GeetestUtils
看源码(片段2)中你会发现,他在验证时使用上下文,将其强制转换为activity,所以这里,在初始化时必须传入的是 Activity,那么问题来了,很多时候我们不会直接将其放到activity去调用,更多的是写为一个工具类,在公共的比如网络请求的地方去调用,那么这个时候我们如何获取activity对象呢,在此我直列出代码,在全局保存一个activity来进行随时使用
/** * 获取栈顶activity * 通过注册activity的生命周期监听获取最新的栈顶activity */ private static WeakReference<Activity> app_activity; private void initGlobeActivity() { getApplication().registerActivityLifecycleCallbacks(new Application.ActivityLifecycleCallbacks() { @Override public void onActivityCreated(Activity activity, Bundle savedInstanceState) { app_activity = new WeakReference<>(activity); Log.e("onActivityCreated===", app_activity + ""); } @Override public void onActivityDestroyed(Activity activity) { } /** Unused implementation **/ @Override public void onActivityStarted(Activity activity) { app_activity = new WeakReference<>(activity); } @Override public void onActivityResumed(Activity activity) { app_activity = new WeakReference<>(activity); } @Override public void onActivityPaused(Activity activity) { } @Override public void onActivityStopped(Activity activity) { } @Override public void onActivitySaveInstanceState(Activity activity, Bundle outState) { } }); }
在此我们就拿到了栈顶的activity,记得一定要用弱引用。
结束语
在此极验验证的集成问题已经介绍完了,如果有什么疑问可以博客留言或者发送邮件到elvis@guojiang.tv。
如果觉得可以帮到你那么就拉倒底部,赞一个。
实现方式已粘贴到博客,所以在此就不下发下载链接了。
- 【集成】极验验证
- iis集成验证小结
- 验证短信集成
- 短信验证集成步骤
- 集成验证码
- 短信验证集成步骤
- 短信验证集成步骤
- 如何集成Windows login, forms集成验证?
- Silverlight + WCF - Windows集成验证
- 第二十二章 集成验证码
- 第二十二章 集成验证码
- SpringMVC集成google验证码
- shareSdk集成短信验证码
- S2SM集成Shiro-登录验证
- springboot集成kaptcha验证码
- springboot集成验证码功能
- jenkins 集成 redmine 账户验证的方案
- ASP.NET MVC - Windows集成验证问题
- 两条Linux删数据跑路命令
- dedecms修改文章标题限制长度
- android 监听网络状态
- 怎样调试静态lib
- 验证是否为空并抛异常
- 【集成】极验验证
- git使用遇到的问题
- jsp页面截取字符串
- Python中partial的使用
- eclipse报错Address already in use: JVM_Bind(端口冲突)
- 使用 web 代理实现 Ajax 跨域调用
- (hibernate)Executing an update/delete query
- 20170628《Trying Not To Try:The Art and Science of Spontaneity》
- Codeforces Round #421 (Div. 2) | A. Mister B and Book Reading