flutter 人机验证实战

先看效果

基本思路

接口进行触发是否进行图像验证,验证后将结果携带到接口里面去,进行人机验证

使用的技术(可惜只有web版本的)

验证码2.0智能人机验证(VAPTCHA)- 安全、易用、完全免费手势验证码VAPTCHA是基于人工智能和大数据的次世代人机验证解决方案。独有的验证策略及风控模型组合可彻底杜绝刷票、灌水、撞库等恶意攻击行为。icon-default.png?t=N7T8https://www.vaptcha.com/

本来想使用flutter 实现一个插件 来调用安卓的ios,写的过程发现 vaptcha 的原生使用的是webview实现的,额 还是使用web版本进行封装把

代码如下

webview代码

import 'dart:convert';
import 'dart:io';

import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';

class AppWebView extends StatefulWidget {
  final String url;
  final Function(dynamic)? onMessageReceived;
  const AppWebView({
    super.key,
    required this.url,
    this.onMessageReceived,
  });

  @override
  State<AppWebView> createState() => _AppWebViewState();
}

class _AppWebViewState extends State<AppWebView> {
  late final WebViewController controller;

  int progress = 0;

  @override
  void initState() {
    super.initState();
    controller = WebViewController()
      ..setJavaScriptMode(JavaScriptMode.unrestricted)
      ..addJavaScriptChannel("lh", onMessageReceived: onMessageReceived)
      ..enableZoom(true)
      ..setBackgroundColor(const Color(0x00000000))
      ..setNavigationDelegate(
        NavigationDelegate(
          onProgress: (int progress) {
            // Update loading bar.
            this.progress = progress;
            setState(() {});
          },
          onPageStarted: (String url) {},
          onPageFinished: (String url) {},
          onWebResourceError: (WebResourceError error) {},
          onNavigationRequest: (NavigationRequest request) {
            if (request.url.startsWith('https://www.youtube.com/')) {
              return NavigationDecision.prevent;
            }
            return NavigationDecision.navigate;
          },
        ),
      )
      ..loadRequest(Uri.parse(widget.url));
  }

  // 接受h5发送来的数据
  onMessageReceived(message) async {
    widget.onMessageReceived?.call(message);
    //接收H5发过来的数据
    String sendMesStr = message.message;
    print("onMessageReceived sendMesStr:${sendMesStr}");
    Map<String, dynamic> msg = json.decode(sendMesStr);

    String method = msg["method"] ?? "";
    // Map<String, dynamic> data = msg["data"] ?? {};
    if (method.isNotEmpty) {
      switch (method) {
        case "back":
          controller.goBack();
          break;
      }
    }
  }

  @override
  Widget build(BuildContext context) {
    if (!kIsWeb && (Platform.isIOS || Platform.isAndroid)) {
      return Scaffold(
        // appBar: AppBar(title: const Text('Flutter Simple Example')),
        body: Stack(children: [
          WebViewWidget(controller: controller),
          if (progress != 100)
            const Center(
              child: CupertinoActivityIndicator(),
            )
        ]),
      );
    } else {
      return const Center(
        child: Text('WebView control is not supported on this platform yet.'),
      );
    }
  }
}

封装的核心

import 'dart:convert';

import 'package:LS/common/api/api.dart';
import 'package:LS/common/utils/toast.dart';
import 'package:LS/common/widgets/app_webview.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:get/get.dart';

class Captcha {
  static show() {
    AppToast.dialog(
      title: "图像验证".tr,
      showBtn: false,
      SizedBox(
        height: 350.h,
        child: const AppWebView(
          url: "https://genaertest.wbnr.xyz/captcha",
          onMessageReceived: onMessageReceived,
        ),
      ),
    );
  }

  static onMessageReceived(message) async {
    //接收H5发过来的数据
    String sendMesStr = message.message;
    print("onMessageReceived sendMesStr:${sendMesStr}");
    Map<String, dynamic> msg = json.decode(sendMesStr);

    String method = msg["method"] ?? "";
    Map<String, dynamic> data = msg["data"] ?? {};
    String server = data["server"] ?? "";
    String token = data["token"] ?? "";
    if (method.isNotEmpty) {
      switch (method) {
        case "getServerToken":
          try {
            // 调用后端接口
            final res = await Api.captchaVerify(server: server, token: token);
            final data = res["data"] ?? {};
            if (data["success"] == 1) {
              AppToast.show("验证通过");
            }
            // 关闭 SmartDialog  弹窗
            SmartDialog.dismiss();
          } catch (e) {
            SmartDialog.dismiss();
          }
          break;
      }
    }
  }
}

弹窗使用的是flutter_smart_dialog 可以自己集成一下

flutter_smart_dialog | Flutter PackageAn elegant Flutter Dialog solution, Easily implement Toast, Loading and custom Dialog, Make the use of the dialog easier!icon-default.png?t=N7T8https://pub-web.flutter-io.cn/packages/flutter_smart_dialog

 AppToast.dialog 其实是下面的封装

 SmartDialog.show(

      builder: (_) {

        return child;

      },

      keepSingle: true,

      clickMaskDismiss: clickMaskDismiss,

      usePenetrate: false,

      maskWidget: maskWidget,

    );

然后是网页代码

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title></title>
    <style>
      /*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */
      html {
        line-height: 1.15;
        -webkit-text-size-adjust: 100%;
      }
      body {
        margin: 0;
      }
      main {
        display: block;
      }
      h1 {
        font-size: 2em;
        margin: 0.67em 0;
      }
      hr {
        box-sizing: content-box;
        height: 0;
        overflow: visible;
      }
      pre {
        font-family: monospace, monospace;
        font-size: 1em;
      }
      a {
        background-color: transparent;
      }
      abbr[title] {
        border-bottom: none;
        text-decoration: underline;
        text-decoration: underline dotted;
      }
      b,
      strong {
        font-weight: bolder;
      }
      code,
      kbd,
      samp {
        font-family: monospace, monospace;
        font-size: 1em;
      }
      small {
        font-size: 80%;
      }
      sub,
      sup {
        font-size: 75%;
        line-height: 0;
        position: relative;
        vertical-align: baseline;
      }
      sub {
        bottom: -0.25em;
      }
      sup {
        top: -0.5em;
      }
      img {
        border-style: none;
      }
      button,
      input,
      optgroup,
      select,
      textarea {
        font-family: inherit;
        font-size: 100%;
        line-height: 1.15;
        margin: 0;
      }
      button,
      input {
        overflow: visible;
      }
      button,
      select {
        text-transform: none;
      }
      [type="button"],
      [type="reset"],
      [type="submit"],
      button {
        -webkit-appearance: button;
      }
      [type="button"]::-moz-focus-inner,
      [type="reset"]::-moz-focus-inner,
      [type="submit"]::-moz-focus-inner,
      button::-moz-focus-inner {
        border-style: none;
        padding: 0;
      }
      [type="button"]:-moz-focusring,
      [type="reset"]:-moz-focusring,
      [type="submit"]:-moz-focusring,
      button:-moz-focusring {
        outline: 1px dotted ButtonText;
      }
      fieldset {
        padding: 0.35em 0.75em 0.625em;
      }
      legend {
        box-sizing: border-box;
        color: inherit;
        display: table;
        max-width: 100%;
        padding: 0;
        white-space: normal;
      }
      progress {
        vertical-align: baseline;
      }
      textarea {
        overflow: auto;
      }
      [type="checkbox"],
      [type="radio"] {
        box-sizing: border-box;
        padding: 0;
      }
      [type="number"]::-webkit-inner-spin-button,
      [type="number"]::-webkit-outer-spin-button {
        height: auto;
      }
      [type="search"] {
        -webkit-appearance: textfield;
        outline-offset: -2px;
      }
      [type="search"]::-webkit-search-decoration {
        -webkit-appearance: none;
      }
      ::-webkit-file-upload-button {
        -webkit-appearance: button;
        font: inherit;
      }
      details {
        display: block;
      }
      summary {
        display: list-item;
      }
      template {
        display: none;
      }
      [hidden] {
        display: none;
      }
      /*# sourceMappingURL=normalize.min.css.map */
    </style>
    <style>
      .VAPTCHA-init-main {
        display: table;
        width: 100%;
        height: 100%;
        background-color: #eeeeee;
        position: fixed;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
      }

      .VAPTCHA-init-loading {
        display: table-cell;
        vertical-align: middle;
        text-align: center;
      }

      .VAPTCHA-init-loading > a {
        display: inline-block;
        width: 18px;
        height: 18px;
        border: none;
      }

      .VAPTCHA-init-loading .VAPTCHA-text {
        font-family: sans-serif;
        font-size: 12px;
        color: #cccccc;
        vertical-align: middle;
      }
      #VAPTCHAContainer {
        width: 240px;
        height: 36px;
        position: fixed;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
      }
    </style>
    <!-- <script src="https://v-cn.vaptcha.com/v3.js"></script> -->
    <script>
      !(function () {
        "use strict";
        function e(e) {
          return e === undefined || null === e;
        }
        function t(e) {
          return e !== undefined && null !== e;
        }
        function n(e) {
          return null !== e && "object" === (void 0 === e ? "undefined" : p(e));
        }
        function a(e) {
          return (
            "object" === (void 0 === e ? "undefined" : p(e)) &&
            e instanceof HTMLElement
          );
        }
        function r(e) {
          var t = e && e.toString().match(/^\s*function (\w+)/);
          return t ? t[1] : "";
        }
        function o(e) {
          var t =
            arguments.length > 1 && arguments[1] !== undefined
              ? arguments[1]
              : {};
          for (var n in t) e[n] = t[n];
          return e;
        }
        function i(e) {
          var t = Object.create(null);
          return function (n) {
            return t[n] || (t[n] = e(n));
          };
        }
        function c(e) {
          return h.call(e).slice(8, -1);
        }
        function u(e) {
          throw new Error(e);
        }
        function l() {
          if (navigator.cookieEnabled) {
            localStorage.setItem("vaptchatemp1", "1");
            var e = localStorage.getItem("vaptchatemp1");
            return localStorage.removeItem("vaptchatemp1"), !!e;
          }
          return !1;
        }
        function Promise(e) {
          var t = this;
          (this.state = "pending"),
            (this.value = undefined),
            (this.reason = undefined),
            (this.onResolveAsyncCallbacks = []),
            (this.onRejectAsyncCallbacks = []);
          var n = function (e) {
              "pending" === t.state &&
                ((t.state = "fulfilled"),
                (t.value = e),
                t.onResolveAsyncCallbacks.map(function (e) {
                  return e();
                }));
            },
            a = function (e) {
              "pending" === t.state &&
                ((t.state = "rejected"),
                (t.reason = e),
                t.onRejectAsyncCallbacks.map(function (t) {
                  return t(e);
                }));
            };
          try {
            e(n, a);
          } catch (r) {
            a(r);
          }
        }
        function s(e, t) {
          if (!(e instanceof t))
            throw new TypeError("Cannot call a class as a function");
        }
        function f() {
          var e = navigator.language || navigator.userLanguage;
          return "zh-CN" === e
            ? "zh-CN"
            : "zh-TW" === e
            ? "zh-TW"
            : e.includes("en", -1)
            ? "en"
            : e.includes("ja", -1)
            ? "jp"
            : e.includes("vi", -1)
            ? "vi"
            : "zh-CN";
        }
        (window.HTMLElement = window.HTMLElement || Element),
          Array.prototype.map ||
            (Array.prototype.map = function (e, t) {
              var n, a, r;
              if (null == this)
                throw new TypeError(" this is null or not defined");
              var o = Object(this),
                i = o.length >>> 0;
              if ("[object Function]" != Object.prototype.toString.call(e))
                throw new TypeError(e + " is not a function");
              for (t && (n = t), a = new Array(i), r = 0; r < i; ) {
                var c, u;
                r in o && ((c = o[r]), (u = e.call(n, c, r, o)), (a[r] = u)),
                  r++;
              }
              return a;
            }),
          Array.prototype.includes ||
            (Array.prototype.includes = function (e, t) {
              if (null == this)
                throw new TypeError('"this" is null or not defined');
              var n = Object(this),
                a = n.length >>> 0;
              if (0 === a) return !1;
              for (
                var r = 0 | t, o = Math.max(r >= 0 ? r : a - Math.abs(r), 0);
                o < a;

              ) {
                if (n[o] === e) return !0;
                o++;
              }
              return !1;
            }),
          Array.prototype.findIndex ||
            (Array.prototype.findIndex = function (e) {
              if (null == this)
                throw new TypeError('"this" is null or not defined');
              var t = Object(this),
                n = t.length >>> 0;
              if ("function" != typeof e)
                throw new TypeError("predicate must be a function");
              for (var a = arguments[1], r = 0; r < n; ) {
                if (e.call(a, t[r], r, t)) return r;
                r++;
              }
              return -1;
            }),
          Object.create ||
            (Object.create = function (e) {
              var t = function () {};
              return (t.prototype = e), new t();
            });
        var d = {
            vid: null,
            scene: 0,
            container: null,
            mode: "popup",
            style: "dark",
            lang: "auto",
            ai: !0,
            https: !0,
            guide: !0,
            aiAnimation: !1,
            protocol: "https://",
            css_version: "2.9.12",
            cdn_servers: ["statics.vaptcha.com"],
            api_server: "api.vaptcha.com/v3",
            canvas_path: "/canvas.min.js",
            offline_server: "",
          },
          p =
            "function" == typeof Symbol && "symbol" == typeof Symbol.iterator
              ? function (e) {
                  return typeof e;
                }
              : function (e) {
                  return e &&
                    "function" == typeof Symbol &&
                    e.constructor === Symbol &&
                    e !== Symbol.prototype
                    ? "symbol"
                    : typeof e;
                },
          h = Object.prototype.toString,
          v =
            (i(function (e) {
              for (
                var t = {},
                  n =
                    (e && -1 !== e.indexOf("?") && e.split("?")[1]) ||
                    window.location.search.substring(1),
                  a = n.split("&"),
                  r = 0;
                r < a.length;
                r++
              ) {
                var o = a[r].split("=");
                t[decodeURIComponent(o[0])] = decodeURIComponent(o[1]);
              }
              return t;
            }),
            i(function (e) {
              return e.charAt(0).toUpperCase() + e.slice(1);
            })),
          g = function (t) {
            (this.data = t),
              (this.valiudateFuns = []),
              (this.ruleFuns = {
                required: function (t, n) {
                  return e(t) || 0 === t.length ? n : null;
                },
              });
          };
        g.prototype = {
          constructor: g,
          addValidateRules: function (e) {
            o(this.ruleFuns, e);
          },
          add: function (e, t, n) {
            var a = this,
              r = t.split(":"),
              o = r.shift(),
              i = this.ruleFuns[o];
            r.unshift(this.data[e]),
              r.push(n),
              i
                ? this.valiudateFuns.push(function () {
                    return i.apply(a, r);
                  })
                : console.warn(
                    "Validator warning: rule " + o + " is not defined"
                  );
          },
          validate: function () {
            for (var e, t = 0; (e = this.valiudateFuns[t++]); ) {
              var n = e();
              if (n) return u(n), !1;
            }
            return !0;
          },
        };
        var m = {
          AccessDenied: "0101",
          RefreshAgain: "0102",
          Success: "0103",
          Fail: "0104",
          RefreshTooFast: "0105",
          RefreshTanto: "0106",
          DrawTanto: "0107",
          Attack: "0108",
          jsonpTimeOut: "0703",
          challengeExpire: "1002",
        };
        (Promise.prototype.then = function (e) {
          var t = this;
          if ("fulfilled" === this.state) {
            var a = e(this.value);
            if (n(a) && "Promise" === r(a.constructor)) return a;
          }
          return "pending" === this.state
            ? new Promise(function (a) {
                t.onResolveAsyncCallbacks.push(function () {
                  var o = e(t.value);
                  if (n(o) && "Promise" === r(o.constructor)) return o.then(a);
                  a(o);
                });
              })
            : this;
        }),
          (Promise.prototype["catch"] = function (e) {
            return (
              "rejected" === this.state && e(this.reason),
              "pending" === this.state && this.onRejectAsyncCallbacks.push(e),
              this
            );
          }),
          (Promise.resolve = function (e) {
            return new Promise(function (t) {
              t(e);
            });
          }),
          (Promise.reject = function (e) {
            return new Promise(function (t, n) {
              n(e);
            });
          });
        var y = (function () {
            function e(e, t) {
              for (var n = 0; n < t.length; n++) {
                var a = t[n];
                (a.enumerable = a.enumerable || !1),
                  (a.configurable = !0),
                  "value" in a && (a.writable = !0),
                  Object.defineProperty(e, a.key, a);
              }
            }
            return function (t, n, a) {
              return n && e(t.prototype, n), a && e(t, a), t;
            };
          })(),
          w = (function () {
            function e() {
              s(this, e);
            }
            return (
              y(e, [
                {
                  key: "GenerateFP",
                  value: function () {
                    return this.extractCRC32FromBase64(
                      this.getComplexCanvasFingerprint(
                        arguments.length > 0 && arguments[0] !== undefined
                          ? arguments[0]
                          : ""
                      )
                    );
                  },
                },
                {
                  key: "getComplexCanvasFingerprint",
                  value: function () {
                    var e =
                        arguments.length > 0 && arguments[0] !== undefined
                          ? arguments[0]
                          : "",
                      t = "BrowserLeaks,com <canvas> 1.0" + e,
                      n = document.createElement("canvas");
                    n.setAttribute("width", "220"),
                      n.setAttribute("height", "30");
                    var a = n.getContext("2d");
                    return (
                      (a.textBaseline = "top"),
                      (a.font = "14px 'Arial'"),
                      (a.textBaseline = "alphabetic"),
                      (a.fillStyle = "#f60"),
                      a.fillRect(125, 1, 62, 20),
                      (a.fillStyle = "#069"),
                      a.fillText(t, 2, 15),
                      (a.fillStyle = "rgba(102, 204, 0, 0.7)"),
                      a.fillText(t, 4, 17),
                      n.toDataURL()
                    );
                  },
                },
                {
                  key: "extractCRC32FromBase64",
                  value: function (e) {
                    return (
                      (e = e.replace("data:image/png;base64,", "")),
                      this.string2Hex(atob(e).slice(-16, -12).toString())
                    );
                  },
                },
                {
                  key: "string2Hex",
                  value: function (e) {
                    for (var t = "", n = 0; n < e.length; n++) {
                      var a = e.charCodeAt(n);
                      a <= 15 && (t += "0"),
                        (t += a.toString(16).toLocaleUpperCase());
                    }
                    return t;
                  },
                },
              ]),
              e
            );
          })(),
          T =
            (new w(),
            (function () {
              var e = d.protocol,
                t = d.api_server,
                n = function (e) {
                  var t = "";
                  for (var n in e)
                    Object.prototype.hasOwnProperty.call(e, n) &&
                      (t += "&" + n + "=" + encodeURIComponent(e[n]));
                  return t;
                },
                a = function (a, r) {
                  var o = n(r),
                    i = a.indexOf("http://") > -1 || a.indexOf("https://") > -1;
                  return (
                    a.indexOf("?") < 0 && (o = "?" + o.slice(1)),
                    i ? "" + a + o : "" + e + t + a + o
                  );
                },
                r = function (e) {
                  var t = document.getElementsByTagName("head")[0],
                    n = document.createElement("script");
                  return (
                    (n.charset = "UTF-8"),
                    (n.src = e),
                    t.appendChild(n),
                    {
                      remove: function () {
                        t.removeChild(n);
                      },
                    }
                  );
                },
                i = function (e, t, n, i) {
                  return (
                    (t = t || {}),
                    (n = n || !1),
                    new Promise(function (c) {
                      if (n) {
                        var u = setTimeout(function () {
                          clearTimeout(u),
                            l.remove(),
                            c({ code: "0703", msg: "Time out,Refresh Again!" });
                        }, i || 2e3);
                        window["static"] = function () {
                          clearTimeout(u), c.apply(this, arguments), l.remove();
                        };
                        var l = r(e);
                      } else {
                        var s = "VaptchaJsonp" + new Date().valueOf();
                        window[s] && (s += "1"),
                          o(t, { callback: s }),
                          (e = a(e, t));
                        var f = r(e),
                          d = setTimeout(function () {
                            clearTimeout(d),
                              (window[s] = null),
                              f.remove(),
                              c({
                                code: "0703",
                                msg: "Time out,Refresh Again!",
                              });
                          }, 1e4);
                        window[s] = function () {
                          clearTimeout(d),
                            c.apply(this, arguments),
                            f.remove(),
                            (window[s] = null);
                        };
                      }
                    })
                  );
                };
              return (
                (i.setConfig = function (n) {
                  (e = n.protocol || e), (t = n.api_server || t);
                }),
                i
              );
            })()),
          S = {
            staticConfig: function (e) {
              return T(
                e.protocol + e.url + e.type + e.id,
                {},
                !0,
                e.waitTime || 2e3
              );
            },
            getConfig: function (e) {
              var n = "";
              return (
                l() &&
                  t(localStorage.getItem("vaptchanu")) &&
                  (n = localStorage.getItem("vaptchanu")),
                T("/config", {
                  vi: e.vid,
                  t: e.mode,
                  s: e.scene || 0,
                  z: e.zone,
                  v: 3,
                  u: n,
                })
              );
            },
            lang: function (e) {
              return T("http://localhost:8080/api/v1/lang", {}, !1);
            },
          },
          C = {
            en: {
              "0201": "id empty",
              "0202": "id error",
              "0208": "scene error",
              "0209": "request used up",
              "0906": "params error",
              "0702": "VAPTCHA unit does not match the domain name",
              "0105": "Request too fast, try again later!",
            },
            "zh-CN": {
              "0702": "验证单元与域名不匹配",
              "0105": "刷新过快,请稍后再试。",
            },
          },
          b = 0,
          j = 9999999999999,
          I = 0,
          N = 9999999999999,
          A = (function () {
            function r() {
              var e = navigator.language || navigator.userLanguage;
              return "zh-CN" === e
                ? "zh-CN"
                : "zh-TW" === e
                ? "zh-TW"
                : e.includes("en", -1)
                ? "en"
                : e.includes("ja", -1)
                ? "jp"
                : "zh-CN";
            }
            function i(e) {
              if ("cn" === e.area) return "cn";
              if ("sea" === e.area) return "sea";
              if ("na" === e.area) return (e.area = "sea"), "sea";
              if (
                t(localStorage.getItem("vaptchaNetway")) &&
                "" !== localStorage.getItem("vaptchaNetway")
              )
                return (
                  o(e, { area: localStorage.getItem("vaptchaNetway") }),
                  localStorage.getItem("vaptchaNetway")
                );
              var n = 0 - new Date().getTimezoneOffset() / 60,
                a = navigator.language || window.navigator.userLanguage;
              return (
                (a = a.toLowerCase()),
                8 === n && "zh-cn" === a
                  ? (o(e, { area: "cn" }), "cn")
                  : 8 === n && "zh-cn" !== a
                  ? (o(e, { area: "sea" }), "sea")
                  : (n >= 6 && n < 8) || (n > 8 && n <= 10)
                  ? (o(e, { area: "sea" }), "na")
                  : (o(e, { area: "na" }), "na")
              );
            }
            var l = !1,
              s = function (e) {
                var n = void 0,
                  a = void 0;
                return (
                  t(e.area)
                    ? ((n = "channel-" + i(e) + ".vaptcha.net/" + i(e)),
                      (a = "api-" + i(e) + ".vaptcha.net"))
                    : (o(e, { area: "cn" }),
                      (n = "channel-cn.vaptcha.net/cn"),
                      (a = "api-cn.vaptcha.net")),
                  (b = new Date().getTime()),
                  t(localStorage.getItem("vaptchaSpareCh")) &&
                  new Date().getTime() -
                    localStorage.getItem("vaptchaSpareCh") <
                    36e5
                    ? S.staticConfig({
                        protocol: e.protocol,
                        id: e.vid,
                        url: n,
                        type: "/config/",
                      }).then(function (a) {
                        if (
                          ((j = new Date().getTime()), w(i(e), e), t(a.alias))
                        )
                          return S.staticConfig({
                            protocol: e.protocol,
                            id: a.alias,
                            url: n,
                            type: "/alias/",
                          }).then(function (e) {
                            return o(e, { state: a.state }), Promise.resolve(e);
                          });
                        console.log("channel error");
                      })
                    : S.staticConfig({
                        protocol: e.protocol,
                        url: a,
                        type: "/channel/",
                        id: e.vid,
                        waitTime: 5e3,
                      }).then(function (a) {
                        return (
                          (j = new Date().getTime()),
                          w(i(e), e),
                          t(a.msg)
                            ? (localStorage.setItem(
                                "vaptchaSpareCh",
                                new Date().getTime()
                              ),
                              S.staticConfig({
                                protocol: e.protocol,
                                id: e.vid,
                                url: n,
                                type: "/config/",
                              }).then(function (a) {
                                if (t(a.alias))
                                  return S.staticConfig({
                                    protocol: e.protocol,
                                    id: a.alias,
                                    url: n,
                                    type: "/alias/",
                                  }).then(function (e) {
                                    return (
                                      o(e, { state: a.state }),
                                      Promise.resolve(e)
                                    );
                                  });
                                console.log("channel error");
                              }))
                            : Promise.resolve(a)
                        );
                      })
                );
              },
              f = function (e) {
                return s(e)
                  .then(function (n) {
                    if (t(n.code) && "0703" === n.code)
                      return (
                        u("5001: channel interface timeout"),
                        Promise.reject("5001: channel interface timeout")
                      );
                    o(e, { api_server: n.api }), T.setConfig(e);
                    var a = 0 - new Date().getTimezoneOffset() / 60;
                    return o(e, { zone: a }), S.getConfig(e);
                  })
                  .then(function (n) {
                    if (t(n.code) && "0703" === n.code)
                      return (
                        u("5002: config interface timeout"),
                        Promise.reject("5002: config interface timeout")
                      );
                    if (!n) return Promise.resolve();
                    if (n.code !== m.Success) {
                      var a = C.en;
                      return (
                        "0702" === n.msg
                          ? alert("" + a[n.msg])
                          : "0105" === n.code
                          ? alert("" + a[n.code])
                          : console.log("errorCode:" + n.code + ":" + n.msg),
                        u(a[n.msg] || n.msg),
                        Promise.reject(n.code)
                      );
                    }
                    return (
                      n.data.guideVersion && n.data.guideVersion > "3.2.0"
                        ? ((n.data.v3Update = 0),
                          console.log(
                            "Sorry,the version of V3.JS is too low, please upgrade!"
                          ))
                        : (n.data.v3Update = 1),
                      o(e, n.data),
                      Promise.resolve()
                    );
                  });
              },
              d = function (e, t) {
                return e.protocol + "static-" + e.area + ".vaptcha.net/" + t;
              },
              p = function (t) {
                var n = document.getElementsByTagName("head")[0],
                  a = document.getElementById("vaptcha_style");
                return new Promise(function (r) {
                  e(a)
                    ? ((a = document.createElement("link")),
                      o(a, {
                        rel: "stylesheet",
                        type: "text/css",
                        href: t,
                        id: "vaptcha_style",
                        onload: r,
                      }),
                      n && n.appendChild(a))
                    : r();
                });
              },
              h = function O(e) {
                var n = document.getElementsByTagName("head")[0],
                  a = document.querySelector("script[src='" + e + "']");
                return new Promise(function (r) {
                  if (t(a))
                    return void (a.loaded
                      ? r()
                      : setTimeout(function () {
                          return O(e).then(r);
                        }));
                  a = document.createElement("script");
                  var i = function () {
                    (a.readyState &&
                      "loaded" !== a.readyState &&
                      "complete" !== a.readyState) ||
                      (r(),
                      (a.loaded = !0),
                      (a.onload = null),
                      (a.onreadystatechange = null));
                  };
                  o(a, {
                    async: !0,
                    charset: "utf-8",
                    src: e,
                    onerror: function () {
                      return u("load sdk timeout");
                    },
                    onload: i,
                    onreadystatechange: i,
                  }),
                    n.appendChild(a);
                });
              },
              y = function (e) {
                var t = e.sdkName,
                  n = e.config,
                  a = d(n, "js/" + n.js_path);
                return h(a).then(function () {
                  var e = v(t);
                  return Promise.resolve(
                    new (0, window["_" + e + "Vaptcha"])(n)
                  );
                });
              },
              w = function (e, n) {
                var a = t(localStorage.getItem("vaptchaNetway")),
                  r = t(localStorage.getItem("vaptchaNetwayTime"))
                    ? localStorage.getItem("vaptchaNetwayTime")
                    : 0,
                  o = new Date().getTime() - r,
                  i =
                    (t(localStorage.getItem("vaptchaNetwayTime2")) &&
                      localStorage.getItem("vaptchaNetwayTime2"),
                    j - b),
                  c = void 0;
                if (
                  (i < 500 &&
                    !a &&
                    (localStorage.setItem("vaptchaNetway", e),
                    localStorage.setItem(
                      "vaptchaNetwayTime",
                      new Date().getTime()
                    ),
                    localStorage.setItem("vaptchaNetwayTime2", i)),
                  !a || i >= 500 || o > 864e5)
                ) {
                  e = e.toLowerCase();
                  var u = void 0;
                  u = "cn" == e ? "sea" : "cn";
                  var l = "api-" + u + ".vaptcha.net";
                  (I = new Date().getTime()),
                    S.staticConfig({
                      protocol: n.protocol,
                      url: l,
                      type: "/channel/",
                      id: n.vid,
                      waitTime: 5e3,
                    }).then(function (t) {
                      (N = new Date().getTime()),
                        (c = N - I),
                        i < c &&
                          (localStorage.setItem("vaptchaNetway", e),
                          localStorage.setItem(
                            "vaptchaNetwayTime",
                            new Date().getTime()
                          ),
                          localStorage.setItem("vaptchaNetwayTime2", i)),
                        c < i &&
                          (localStorage.setItem("vaptchaNetway", u),
                          localStorage.setItem(
                            "vaptchaNetwayTime",
                            new Date().getTime()
                          ),
                          localStorage.setItem("vaptchaNetwayTime2", c));
                    });
                }
              },
              A = function (e) {
                if ("auto" === e.lang || "" === e.lang) {
                  var o = r();
                  e.lang = o || "zh-CN";
                }
                (l = !0),
                  (e.https = !0),
                  (e.protocol = "https://"),
                  T.setConfig(e),
                  t(e.type) && (e.mode = e.type),
                  "embedded" === e.mode && (e.mode = "embed"),
                  !["embed", "popup", "invisible"].includes(e.mode) &&
                    (e.mode = "popup"),
                  t(e.mode) && (e.type = e.mode);
                var i = new g(e);
                if (
                  (i.addValidateRules({
                    elementOrSelector: function (t, r) {
                      if (
                        ("String" === c(e.container) &&
                          (e.container = document.querySelector(e.container)),
                        n(e.container) &&
                          a(e.container[0]) &&
                          (e.container = e.container[0]),
                        !a(e.container))
                      )
                        return r;
                    },
                  }),
                  i.add("vid", "required", "please configure vid"),
                  "invisible" !== e.mode &&
                    i.add(
                      "container",
                      "elementOrSelector",
                      "5004: please configure container with element or selector"
                    ),
                  i.validate())
                )
                  return f(e)
                    .then(function () {
                      var t = e.https
                          ? "css/theme_https." + e.css_version + ".css"
                          : "css/theme." + e.css_version + ".css",
                        n = d(e, t);
                      return p(n);
                    })
                    .then(function () {
                      var t = e.mode;
                      return (l = !1), y({ sdkName: t, config: e });
                    });
              };
            return function k(e) {
              return new Promise(function (t) {
                l
                  ? setTimeout(function () {
                      k(e).then(t);
                    }, 1e3)
                  : A(e).then(t);
              })["catch"](function (e) {
                return (l = !1), u(e), Promise.reject(e);
              });
            };
          })(),
          O = (function () {
            var e = function (e) {
                var n = e.getAttribute("data-config"),
                  a = {};
                if (t(n))
                  try {
                    a = JSON.parse(n);
                  } catch (r) {
                    u("dom config format error");
                  }
                return a;
              },
              n = function (e) {
                var n = e.getAttribute("data-vid");
                return t(n) ? { vid: n } : {};
              },
              a = function (e, n) {
                var a = Object.create(d);
                (a.container = e),
                  o(a, n),
                  t(a.vid) &&
                    A(a).then(function (e) {
                      e.renderTokenInput(), e.render();
                    });
              };
            return function () {
              for (
                var t = document.querySelectorAll("[data-vid]"),
                  r = document.querySelectorAll("[data-config]"),
                  o = 0;
                o < r.length;
                o++
              ) {
                var i = e(r[o]);
                a(r[o], i);
              }
              for (var c = 0; c < t.length; c++)
                if (!Array.prototype.includes.call(r, t[c])) {
                  var u = n(t[c]);
                  a(t[c], u);
                }
            };
          })();
        (window.onload = O),
          (window.vaptcha = function (e) {
            var t = Object.create(d);
            return (
              o(t, e),
              ("auto" === t.lang || "" === t.lang) && (t.lang = f() || "zh-CN"),
              A(t)
            );
          });
      })();
    </script>
  </head>

  <body>
    <div id="VAPTCHAContainer">
      <!-- 下面代码为预加载动画代码,仅供参考 -->
      <div class="VAPTCHA-init-main">
        <div class="VAPTCHA-init-loading">
          <a href="/" target="_blank">
            <svg
              xmlns="http://www.w3.org/2000/svg"
              xmlns:xlink="http://www.w3.org/1999/xlink"
              width="48px"
              height="60px"
              viewBox="0 0 24 30"
              style="
                enable-background: new 0 0 50 50;
                width: 14px;
                height: 14px;
                vertical-align: middle;
              "
              xml:space="preserve"
            >
              <rect x="0" y="9.22656" width="4" height="12.5469" fill="#CCCCCC">
                <animate
                  attributeName="height"
                  attributeType="XML"
                  values="5;21;5"
                  begin="0s"
                  dur="0.6s"
                  repeatCount="indefinite"
                ></animate>
                <animate
                  attributeName="y"
                  attributeType="XML"
                  values="13; 5; 13"
                  begin="0s"
                  dur="0.6s"
                  repeatCount="indefinite"
                ></animate>
              </rect>
              <rect
                x="10"
                y="5.22656"
                width="4"
                height="20.5469"
                fill="#CCCCCC"
              >
                <animate
                  attributeName="height"
                  attributeType="XML"
                  values="5;21;5"
                  begin="0.15s"
                  dur="0.6s"
                  repeatCount="indefinite"
                ></animate>
                <animate
                  attributeName="y"
                  attributeType="XML"
                  values="13; 5; 13"
                  begin="0.15s"
                  dur="0.6s"
                  repeatCount="indefinite"
                ></animate>
              </rect>
              <rect
                x="20"
                y="8.77344"
                width="4"
                height="13.4531"
                fill="#CCCCCC"
              >
                <animate
                  attributeName="height"
                  attributeType="XML"
                  values="5;21;5"
                  begin="0.3s"
                  dur="0.6s"
                  repeatCount="indefinite"
                ></animate>
                <animate
                  attributeName="y"
                  attributeType="XML"
                  values="13; 5; 13"
                  begin="0.3s"
                  dur="0.6s"
                  repeatCount="indefinite"
                ></animate>
              </rect>
            </svg>
          </a>
          <span class="VAPTCHA-text">Vaptcha Initializing...</span>
        </div>
      </div>
    </div>
    <script>
      function appCallMethod(key, value) {
        window[key] = value;
      }
      function callAppMethod(method, data = {}) {
        try {
          lh.postMessage(
            JSON.stringify({
              method,
              data,
            })
          );
        } catch (error) {}
      }
    </script>

    <script>
      var serverToken = {};
      var data = {};
      function getServerToken() {
        return serverToken;
      }
      function getData() {
        return data;
      }

      vaptcha({
        vid: "65ddaa64d3784602950e7b12",
        mode: "click",
        scene: "1",
        container: "#VAPTCHAContainer",
        area: "auto",
        lang: "en",
      }).then(function (VAPTCHAObj) {
        // 将VAPTCHA验证实例保存到局部变量中
        obj = VAPTCHAObj;

        // 渲染验证组件
        VAPTCHAObj.render();

        // 验证成功进行后续操作
        VAPTCHAObj.listen("pass", function () {
          serverToken = VAPTCHAObj.getServerToken();
          data = {
            server: serverToken.server,
            token: serverToken.token,
            scene: (window["scene"] ?? 1) * 1,
          };
          callAppMethod("getServerToken", data);
        });
      });
    </script>
  </body>
</html>

最后只需要在接口拦截器中 判断错误状态码 然后主动弹起人机验证

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/415475.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

HTML列表

想要在HTML中实现列表功能&#xff0c;无序用<ul>&#xff0c;有序用<ol>&#xff0c;有手就行。 效果图&#xff1a; CODE: <!DOCTYPE html> <html> <body><h2>一个无序 HTML 列表</h2><ul><li>咖啡</li><…

网络爬虫的危害,如何有效的防止非法利用

近年来&#xff0c;不法分子利用“爬虫”软件收集公民隐私数据案件屡见不鲜。2023年8月23日&#xff0c;北京市高级人民法院召开北京法院侵犯公民个人信息犯罪案件审判情况新闻通报会&#xff0c;通报侵犯公民个人隐私信息案件审判情况&#xff0c;并发布典型案例。在这些典型案…

Apache Paimon Append Scalable表解析

1.Append Scalable Table a) 定义 在表属性中配置 ‘bucket’ ‘-1’&#xff0c;将进入 “unaware-bucket mode”&#xff0c;在此模式下不再有桶的概念&#xff0c;也不保证流任务读取数据的顺序&#xff0c;可以将此表视为批量离线表&#xff0c;所有记录都将进入一个目录…

Codeforces Round 929 (Div. 3)

Codeforces Round 929 (Div. 3) Codeforces Round 929 (Div. 3) A. Turtle Puzzle: Rearrange and Negate 题意&#xff1a;可以对整数数组进行两个操作&#xff0c;一是随意重新排列或保持不变&#xff0c;二是选择连续子段元素符号倒转&#xff0c;求可能最大的所有元素和…

hadoop学习中遇到的问题一

由于看视频总是断断续续&#xff0c;经常遇到各种报错&#xff0c;现将遇到的问题进行总结。 hadoop学习中遇到的问题&#xff1a;hadoop拒绝连接 hadoop安装好之后&#xff0c;在本地浏览器输入地址http://192.168.222.102:9870&#xff0c;提示拒绝连接。在网上找了很多相关…

【Quarto】Markdown导出PPT

title: “Quarto Basics” mainfont: “LXGW WenKai Mono” format: revealjs: theme: default incremental: true pptx: incremental: true html: code-fold: true beamer: incremental: true aspectratio: 169 QUARTO 这段代码是一个 YAML 头部&#xff08;front matter&…

Unity(第十一部)场景

游戏有多个场景组成&#xff08;新手村&#xff0c;某某副本&#xff0c;主城&#xff09; 场景是有多个物体组成&#xff08;怪物&#xff0c;地形&#xff0c;玩家等&#xff09; 物体是有多个组件组成&#xff08;刚体组件&#xff0c;自定义脚本&#xff09; 创建场景 编辑…

刷题笔记 洛谷 P1162 填涂颜色

思路来自 大佬 hat.openai.com/c/9c30032e-5fb9-4677-8c15-9ea6530dc6db 题目链接 P1162 填涂颜色 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 思路 搜索 首先 在外面围上一圈0开始搜素 因为题目说将封闭区域内的0变成2 我们可以在外面进行搜索 把外面所有可以搜索…

【LabVIEW 】串口如何读取长度不一致的字符串

工程经验 1、在循环中&#xff0c;加入定时器&#xff0c;这样可以一段时间读取一次。 2、只要获取完整的一帧数据&#xff0c;就可以进行过滤筛选。

Leetcode—82. 删除排序链表中的重复元素 II【中等】

2024每日刷题&#xff08;117&#xff09; Leetcode—82. 删除排序链表中的重复元素 II 实现代码 /*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode() : val(0), next(nullptr) {}* ListNode(int x) : val…

【踏雪无痕的痕四】——0到底是有还是没有?

目录 一、背景介绍三、过程1.0的历史发展&#xff1f;2.如何将0讲给一个刚上一年级的孩子&#xff1f;3.0的边界和意义&#xff1f;4.那四年&#xff0c;到底在培养什么&#xff1f;和0有什么关系&#xff1f; 四、总结 一、背景介绍 最近在看一年级数学&#xff0c;其中介绍到…

几种新能源汽车(纯电、插混、油混、增程)的区别

纯电&#xff1a;顾名思义就是仅用电池驱动。 插混&#xff1a;汽车具备两套独立的动力系统&#xff1a;油动和电动。该种汽车可充电可加油&#xff0c;用油还是用电自己决定。他的系统结构图如下图&#xff1a; 油混&#xff1a;也称为油电混合。他的特点是可加油不可充电&…

前后端分离项目Vue+node.js二手商品交易系统74qb3

校园二手交易网络的开发和使用在不同的地方是有着差别的。在初高中&#xff0c;校园二手交易网也就是简单的买卖物品&#xff1b;但在大学中&#xff0c;通过买卖自己的物品可以建立联系成为朋友&#xff0c;也就是说校园二手交易网不仅仅是一个交易物品的平台&#xff0c;同时…

重拾前端基础知识:CSS

重拾前端基础知识&#xff1a;CSS 前言选择器简单选择器属性选择器组合选择器 插入CSS内嵌样式&#xff08;Inline Style&#xff09;内部样式&#xff08;Internal Style&#xff09;外部样式&#xff08;External Style&#xff09; 层叠颜色背景颜色文本颜色RGB 颜色HEX 颜色…

JS api基础初学

web api基础 变量声明有三个var let 和const 我们应该用那个呢&#xff1f; 首先var先排除&#xff0c;老派写法&#xff0c;问题很多&#xff0c;可以淘汰掉... let or const? 建议&#xff1a;const优先&#xff0c;尽量使用const&#xff0c;原因是&#xff1a; con…

JMeter学习(一)工具简单介绍

一、JMeter 介绍 Apache JMeter是100%纯JAVA桌面应用程序&#xff0c;被设计为用于测试客户端/服务端结构的软件(例如web应用程序)。它可以用来测试静态和动态资源的性能&#xff0c;例如&#xff1a;静态文件&#xff0c;Java Servlet,CGI Scripts,Java Object,数据库和FTP服务…

我在使用 Copilot 时遇到了许可证验证错误。

如果使用的是 Copilot&#xff0c;并收到以下错误消息&#xff0c;请按以下步骤进行操作&#xff1a; We encountered a problem validating your Copilot license. For more information, see https://aka.ms/copilotlicensecheck 请确保使用的是正确的帐户 请确保已使用具…

信钰证券|昨夜,“金龙”大涨

当地时间2月27日&#xff0c;我国资产自开盘一路走高&#xff0c;抢手中概股普涨&#xff0c;纳斯达克我国金龙指数涨2.10%。其中&#xff0c;抱负轿车涨超11%&#xff0c;网易涨超5%&#xff0c;爱奇艺、微博涨超4%。 美股方面&#xff0c;三大指数涨跌纷歧。到收盘&#xff…

npm淘宝镜像报错certificate has expired

1、概述 vue项目使用npm install命令时&#xff0c;突然报错&#xff1a;“...certificate has expired” 2、解决 1.清空缓存&#xff1a;npm cache clean --force 2.修改镜像&#xff08;管理员运行命令行&#xff09;&#xff1a;npm config set registry https:/…

5G双域快网

目录 一、业务场景 二、三类技术方案 2.1、专用DNN方案 2.2、ULCL方案&#xff1a;通用/专用DNNULCL分流 2.3、 多DNN方案-定制终端无感分流方案 漫游场景 一、业务场景 初期双域专网业务可划分为三类业务场景&#xff0c;学校、政务、文旅等行业均已提出公/专网融合访问需…