# 人机校验

在接口安全控制方面，人机校验可以起到关键的防护作用，尤其是在复杂网络环境下，确保系统的安全性和数据的完整性。以下方式提供如何在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&#x20;

* 在管理平台注册新网站 <http://www.google.com/recaptcha/admin> , 填写表单并选择适合你的网站的reCAPTCHA版本（v2或v3）
* 完成注册后，你将获得一个“站点密钥”（Site Key）和一个“秘密密钥”（Secret Key）。 站点密钥用于前端，秘密密钥用于后端验证。<mark style="color:red;">**需要提供给MultiMarket进行后端配置。**</mark>

### 前端集成(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>
```

3. 在接口请求时放入请求头，传给后端进行效验

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

4. 发起接口请求 通过校验：正常返回请求内容 未通过：`{"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
    }
}) 
```

2. 创建 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()
}
```

````
