特点

CabloyJS提炼出了一个验证码通用框架,将验证码调用接口与验证码具体的实现方式隔离开来,从而具有以下特点:

  1. 业务模块只需调用通用的验证码接口,不需考虑验证码实现细节
  2. 可以开发不同难度、不同风格的验证码提供者,而且每个验证码提供者均是独立的模块,达到即插即用的效果
  3. 切换不同的验证码提供者,仅需修改配置即可

架构图

验证码通用框架a-captcha

如何配置验证码提供者

  1. 可以配置不同场景所使用的验证码提供者
  2. 可以添加不同的场景
  3. 可以修改场景的默认值

a-captcha/backend/src/config/config.js

// provider
config.captcha = {
  scenes: {
    default: {
      module: 'a-captchasimple',
      name: 'captcha',
      timeout: 20 * 60 * 1000,
    },
  },
};
名称 说明
scenes.default 缺省场景
  • 场景
名称 说明
module 验证码提供者模块的名称
name 模块提供的验证码前端渲染组件的名称
timeout 验证码的失效时间

如何使用

- 声明使用场景

在模块test-party中声明一个场景,配置如下:

src/module-vendor/test-party/backend/src/config/config.js

// captcha scenes
const _captchaSMS = {
  module: 'a-authsms',
  name: 'captcha',
};
config.captcha = {
  scenes: {
    formMobileVerifyTest: _captchaSMS,
    formCaptchaTest: null, // means using default
  // formCaptchaTest: {
  //   module: 'a-captchasimple',
  //   name: 'captcha',
  // },
  },
};

- 前端验证码渲染

test-party/front/src/kitchen-sink/pages/form-schema-validation/captcha.vue

<template>
  <eb-page>
    ...
          <eb-list-input :label="$text('CaptchaCode')" type="text" clear-button :placeholder="$text('Captcha Code')" v-model="captcha.token" dataPath="captcha/token">
            <div slot="content">
              <eb-component ref="captchaContainer" module="a-captcha" name="captchaContainer" :options="captchaContainerOptions"></eb-component>
            </div>
          </eb-list-input>
    ...        
  </eb-page> 
</template>
<script>
export default {
  data() {
    return {
      item: {
        userName: null,
        password: null,
      },
      validateParams: {
        module: 'test-party',
        validator: 'formCaptchaTest',
      },
      captcha: {
        token: null,
      },
      captchaContainerOptions: {
        props: {
          module: 'test-party',
          sceneName: 'formCaptchaTest',
        },
      },
    };
  },
  ...
  methods: {
    ...
    onPerformValidate() {
      return this.$api.post('kitchen-sink/form-captcha/signup', {
        data: this.item,
        captcha: this.$refs.captchaContainer.getComponentInstance().captchaData({ token: this.captcha.token }),
      }).then(() => {
        return true;
      });
    },
  },
};

</script>
  1. 模块a-captcha提供了一个前端组件captchaContainer,专门负责验证码的渲染。在这里,我们只需用组件eb-component来包裹渲染组件即可

组件captchaContainer会根据实际配置的使用场景,使用验证码提供者模块提供的渲染组件,如模块a-captchasimple提供的渲染组件captcha

  1. 用户输入的验证码保存在变量captcha.token

  2. 调用后端Api接口,将变量captcha传入后台

- 使用中间件captchaVerify

在后端Api接口的路由上使用中间件captchaVerify,中间件captchaVerify会自动验证前端传入的参数captcha.token是否正确,如果不正确会自动抛出异常

由于前端使用组件eb-validate包裹Form表单,因此会自动提示验证失败的信息

test-party/backend/src/routes.js

{ method: 'post', path: 'kitchen-sink/form-captcha/signup', controller: 'testKitchensinkFormSchemaValidation', middlewares: 'captchaVerify,validate',
  meta: {
    captchaVerify: { scene: { name: 'formCaptchaTest' } },
    validate: { validator: 'formCaptchaTest' },
  },
},
  • captchaVerify.scene
名称 说明
module 模块名称,默认为当前模块
name 场景名称
dataKey 从ctx.request.body.[dataKey]获取token,默认为captcha

如何开发验证码提供者

请参考核心模块

名称 说明
a-captchasimple 提供图片验证
a-authsms 提供mobile验证

如何禁用验证行为

在开发阶段,如果不想每次登录都输入验证码,可以配置如下后端参数

a-captcha/backend/src/config/config.js

// configFront
config.configFront = {
  local: {
    disabled: true,
  },
};