Vue + SpringBoot 集成极验验证码插件

极验有一款行为验证的插件,其实就是个验证码插件,包括滑块和点选的验证方式,这里记录一下如何接入基于 Vue + SpringBoot 的 Web 端项目

更多精彩

写在前面的话

  1. jQuery + SpringMVC 集成极验验证码插件
  2. 对插件的具体描述,一些废话,插件相关网址都在上面这篇笔记里
  3. 之前这篇是适用于 PC Web 端的,现在这篇是适用于 Mobile Web 端的

后端对接实现

  1. 后端的具体实现虽然框架不同,一个使用 SpringMVC ,一个则是 SpringBoot ,但具体实现其实没有太大区别
  2. Service 层几乎完全一致,唯一的区别就是 Controller 层的请求方式注解不太一样

下载并接入集成包

  1. 在前面提供的 geetest-java 中可以下载到插件后端环境的集成包,也可以通过 git clone https://github.com/GeeTeam/gt3-java-sdk.git 直接下载
  2. 下载下来其实是 Java 语言的本地文档、DEMO 、SDK 、以及和后端语言配对的前端依赖 JS
    • 我觉得这里后端如果能提供一个在线的 Maven 或 Gradle 依赖地址其实更好
  3. /src/sdk/GeetestLib.javasrc/demo/demo1/GeetestConfig.java 引入到自己项目即可
  4. 打开 GeetestConfig.java ,将其中的 geetest_idgeetest_key 修改成自己的即可
    • 这两个参数需要到他们 极验后台登录 获取,登录后选择行为验证
    • 之后还需要新增验证,填写基本信息后即可拿到这两个值,如下图
    • 左下角的 ID 对应 geetest_id ,KEY 对应 geetest_key
      image

编写验证码服务

  1. 后端验证的逻辑分为两步验证,第一步初始化,其实就是相当于生成验证码,第二步才是用户发起验证请求
  2. 文档中分别使用了 doGet 演示初始化,doPost 演示接收验证请求
  3. 实际项目中当然不会使用 Servlet 来做这些事情,这里使用的是 SpringMVC
  4. 两个操作可以放在同一个 Service 中,例如 CaptchaServiceImpl.java

封装请求参数

  1. 单独封装起来是因为两步验证都会用到
  2. 请求参数其实就是每个用户的唯一标识,文档中使用的是 用户 ID终端类型 以及 IP 地址
  3. 我这里因为是未登录状态下的验证,所以拿不到用户 ID ,所以直接使用的 IP 地址
private HashMap<String, String> getParams() {
    String clientIp = URIUtil.getClientIp(request);

    HashMap<String, String> params = Maps.newHashMap();
    params.put("user_id", clientIp);
    params.put("client_type", "web");
    params.put("ip_address", clientIp);

    return params;
}

生成验证码,对应第一步初始化

  1. getParams() 获取参数就是上一个函数
public String generateCaptcha() {
    // 初始化极验服务
    GeetestLib lib = new GeetestLib(GeetestConfig.getGeetest_id(), GeetestConfig.getGeetest_key(), GeetestConfig.isnewfailback());

    // 验证预处理
    int status = lib.preProcess(getParams());

    // 将服务状态存放到 Session 中,在第二步验证时会用到
    request.getSession().setAttribute(lib.gtServerStatusSessionKey, status);

    // 返回生成字串
    return lib.getResponseStr();
}

接收用户验证请求,并返回存储处理结果

  1. request.getParameter() 可以直接使用,是因为我的 Service 集成了一个通用的父类,在里面直接注入了 HttpServletRequest
  2. 通过 request 获取的参数都不是自定义的,由极验前端的 gt.js 内部提供
  3. saveMessage() 是验证成功后将当前参与验证的手机号和结果存储到 Redis 中,时效 5 分钟
    • 通过行为验证,正式发起验证码请求时,会先通过请求的手机号去 Redis 中获取行为验证结果
    • 存在且成功才会发验证码,否则会提示进行行为验证
  4. TSharkException() 是自定义的异常处理,由 Controller 捕获后抛到前端弹出提示框告知用户
public void checkCaptcha(String mobile) {
    // 初始化极验服务
    GeetestLib lib = new GeetestLib(GeetestConfig.getGeetest_id(), GeetestConfig.getGeetest_key(), GeetestConfig.isnewfailback());

    // 接收前端参数,由前端 JS 内部封装处理
    String challenge = request.getParameter(GeetestLib.fn_geetest_challenge);
    String validate = request.getParameter(GeetestLib.fn_geetest_validate);
    String seccode = request.getParameter(GeetestLib.fn_geetest_seccode);

    // 取出第一步初始化验证时存储的服务状态
    int status = (Integer) request.getSession().getAttribute(lib.gtServerStatusSessionKey);

    int result = 0;

    if (status == 1) {
        // 服务器在线
        result = lib.enhencedValidateRequest(challenge, validate, seccode, getParams());
    } else {
        // 服务器离线
        result = lib.failbackValidateRequest(challenge, validate, seccode);
    }

    if (result == 1) {
        // 保存验证信息
        saveMessage(mobile, new MessageBean(mobile, result));
    } else {
        throw new TSharkException("行为验证失败,请检查使用环境");
    }
}

控制层定义请求

  1. 因为是前后分离项目,所以使用 @RestController@GetMapping 以及 @PostMapping 来区分请求
  2. SimpleActionHandler 是自定义封装的 Service 异常处理类
    • request 在继承的 AbstractBaseController 自定义父类中统一声明
  3. ResponseData 是自定义封装的返回结果类
  4. 后端的服务就完成了,实现起来还是非常简洁的,点个赞
@Api("行为验证")
@RestController
@RequestMapping("/api/captcha")
public class CaptchaController extends AbstractBaseController {

    @Autowired
    private CaptchaServiceImpl captchaService;

    @ApiOperation("生成行为验证")
    @GetMapping("")
    public ResponseData init() {
        return new SimpleActionHandler(request) {
            @Override
            public void doAction(ResponseData responseData) throws Exception {
                responseData.setData(captchaService.generateCaptcha());
            }
        }.handle();
    }

    @ApiOperation("进行行为验证")
    @PostMapping("")
    public ResponseData check(@RequestParam final String mobile) {
        return new SimpleActionHandler(request) {
            @Override
            public void doAction(ResponseData responseData) throws Exception {
                captchaService.checkCaptcha(mobile);
            }
        }.handle();
    }

}

前端对接实现

  1. 前端使用的是 Vue ,但官网文档只提供了普通的 jQuery 版本集成方式

前端依赖 JS 在哪里

  1. 前端依赖的 JS 在 geetest-WEB-front 接口文档中是找不到的,因为不同服务端语言对应的 JS 不一样,所以将其放置在了后端集成包中
  2. 具体位置如下图所示


    image
  3. 官方也给了相关提示,如下图


    image

引入前端依赖 JS

  1. gt.js 直接复制到项目对应的 JS 目录中,然后通过以下方式引入到需要使用的界面
<script type="text/ecmascript-6">
  import 'assets/plugins/geetest/gt'

  export default { ... }
</script>

准备一个 HTML 区域用于显示行为验证组件

  1. 行为验证组件到底放在你自己页面的什么地方,都行,这里只是提供一个样例
  2. mt-cellMINT UI 的组件
<mt-cell class="captcha-wrapper">
  <div class="captcha register-captcha"></div>
</mt-cell>

初始化行为验证插件

  1. 初始化方式其实没有什么变化
  2. 我这里加了三个参数传入是因为注册和忘记密码都存在发送验证码的行为,所以都需要行为验证
    • className 是行为验证所处的容器
    • objobjCheck 是注册或忘记密码时填写的信息内容也内容验证状态
export default {
  mounted () {
    this._initGeeTest('register-captcha', this.register, this.rstate)
  },
  methods: {
    // 初始化行为验证
    _initGeeTest (className, obj, objCheck) {
      // 清空之前的历史
      this.captchaStatus = false
      document.getElementsByClassName(className)[0].innerHTML = ''

      this.$fetch.captcha.generate().then((res) => {
        let result = JSON.parse(res.data)

        window.initGeetest({
          gt: result.gt,
          challenge: result.challenge,
          new_captcha: result.new_captcha,
          offline: !result.success,
          product: 'float',
          width: '100%'
        }, (captchaObj) => {
          captchaObj.appendTo(`.${className}`)

          captchaObj.onSuccess(() => {
            // 手机号验证
            if (!this._mobileCheck(obj, objCheck)) {
              captchaObj.reset()
              return false
            }

            let result = captchaObj.getValidate()

            this.$fetch.captcha.check({
              mobile: obj.username,
              geetest_challenge: result.geetest_challenge,
              geetest_validate: result.geetest_validate,
              geetest_seccode: result.geetest_seccode
            }).then((res) => {
              if (!res.success) {
                this.captchaStatus = false
                this.$toast.error(res.data)
                captchaObj.reset()
              } else {
                this.captchaStatus = true
              }
            })
          })
        })
      })
    }
  }
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,383评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,522评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,852评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,621评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,741评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,929评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,076评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,803评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,265评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,582评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,716评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,395评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,039评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,027评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,488评论 2 361
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,612评论 2 350

推荐阅读更多精彩内容