人机校验

在接口安全控制方面,人机校验可以起到关键的防护作用,尤其是在复杂网络环境下,确保系统的安全性和数据的完整性。以下方式提供如何在MultiMarket系统中接入人机校验:

接入方式

该功能是对接谷歌官方的reCAPTCHA,https://developers.google.com/recaptcha

涉及接口

login/customer.app.CustomerWebApiService.login global/message.app.VerificationApiService.verifyCodeSend register/customer.app.CustomerWebApiService.register

headrs: {
   // 请求头添加 google captcha
   captcha: zxksjkdjskdjsd
}

接入步骤

详细对接文档可见:https://developers.google.com/recaptcha/docs/display

注册谷歌 reCAPTCHA

  • 在管理平台注册新网站 http://www.google.com/recaptcha/admin , 填写表单并选择适合你的网站的reCAPTCHA版本(v2或v3)

  • 完成注册后,你将获得一个“站点密钥”(Site Key)和一个“秘密密钥”(Secret Key)。 站点密钥用于前端,秘密密钥用于后端验证。需要提供给MultiMarket进行后端配置。

前端集成(JS/V3) 示例

1.将以下代码添加到您的 HTML 页面中,通常放在 标签内

<script src="https://www.google.com/recaptcha/api.js?render=your_site_key"></script>

将 your_site_key 替换为您在管理控制台中获取的站点密钥。

2.根据需求在当用户提交表单(登录、注册、获取验证码等)时执行调用 grecaptcha.execute 方法获取接口请求所需参数 captcha

   <script>
      function onClick(e) {
        e.preventDefault();
        grecaptcha.ready(function() {
          grecaptcha.execute('reCAPTCHA_site_key', {action: 'submit'}).then(function(token) {
              // Add your logic to submit to your backend server here.
          });
        });
      }
  </script>
  1. 在接口请求时放入请求头,传给后端进行效验

headrs: {
   // 请求头添加 google captcha
   captcha: zxksjkdjskdjsd
}
  1. 发起接口请求 通过校验:正常返回请求内容 未通过:{"msg":"请求参数不合法","code":"F999999","bizCode":"G"}

前端集成(Vue/V3) 示例

  1. 下载引入 vue-recaptcha-v3

npm i vue-recaptcha-v3 --save
// main.js
import { VueReCaptcha } from 'vue-recaptcha-v3'
app.use(VueReCaptcha, {
    // 替换为您在管理控制台中获取的站点密钥
    siteKey: '6LcNvBUqAAAAABz2_ieWJEtdmyK_-oUUEk04Y1z4',
    loaderOptions: {
        // 由于某些国家的限制,可以选择开启使用 recaptcha.net 而不是 google.com。
        useRecaptchaNet: true
    }
}) 
  1. 创建 useRecaptcha.js 文件

import { useReCaptcha } from 'vue-recaptcha-v3'
import { reactive, onMounted, toRefs } from 'vue'
import { useStore } from 'vuex'

export default function useRecaptcha () {
    const { executeRecaptcha: _executeRecaptcha, recaptchaLoaded } = useReCaptcha()
    const store = useStore()
    const state = reactive({
        // SDK 加载中
        loading: false,
        // SDK 加载完成
        loaded: false
    })

    onMounted(async () => {
        try {
            state.loading = true
            // 初始化 Google reCAPTCHA SDK
            const res = await recaptchaLoaded()
            if (res) {
                state.loaded = true
            }
        } catch (error) {
            console.log('🚀 ~ onMounted ~ error:', error)
        } finally {
            state.loading = false
        }
    })

    // 获取 Google reCAPTCHA 验证码
    const executeRecaptcha = async () => {
        try {
            const captcha = await _executeRecaptcha('verifyCodeSend')
            await store.commit('_base/UPDATE_captcha', captcha)
            return captcha
            // 更新全局 captcha 数据
        } catch (error) {
            console.log('🚀 ~ executeRecaptcha ~ error:', error)
        }
    }

    return {
        ...toRefs(state),
        executeRecaptcha,
        recaptchaLoaded
    }
}


```
3. 在 vuex store 定义captcha全局数据
```
// src/store/modules/base.js
export default {
   state: { 
      // Google 人机验证 captcha
      captcha: ''
   },
   mutations: {
      // 更新 Google 人机验证 captcha
      UPDATE_captcha (state, data) {
         state.captcha = data
      },
   }
}

```
4. axios拦截器添加错误提示
```
service.interceptors.response.use(
   response => {
      const { data } = response
      if (data.code === 'F999999') {
         // 提示文案需要做多语言处理
         Toast('请求参数不合法')
         return data
      }
      return response
   },
   error => {
      return Promise.reject(error)
   }
)
```
5. 使用示例
```


/** 第一步:引入 useRecaptcha hook   **/
const { executeRecaptcha } = useRecaptcha()


/** 第二步:在发送验证码接口头部添加 captcha 参数   **/
// 发送验证码 
export function verifyCodeSendRequest (data) {
    return request({
        url: '/global/message.app.VerificationApiService.verifyCodeSend',
        method: 'post',
        headers: {
            version: '0.0.1',
            // 请求头添加 google 验证码
            captcha: window.store.state._base.captcha
        },
        data
    })
}

/** 第三步:在需要添加 captcha 参数的接口前面执行executeRecaptcha  **/

// 发送验证码  message.app.VerificationApiService.verifyCodeSend
const verifyCodeSend = async () =>{
 await executeRecaptcha('verifyCodeSend') 
 await verifyCodeSendRequest()
}

// 登录 login/customer.app.CustomerWebApiService.login
const login= async () =>{
 await executeRecaptcha('login') 
 await loginRequest()
}

// 注册接口:register/customer.app.CustomerWebApiService.register
const register = async () =>{
 await executeRecaptcha('register') 
 await registerRequest()
}
```

Last updated