如何在JavaScript fetch无表单提交场景下集成reCAPTCHA验证
结论
完全可以在不改动现有代码结构的前提下集成reCAPTCHA,不需要新增表单容器,不需要修改你已写好的文件输入框、上传按钮标签,只需要补充少量前后端逻辑即可。
具体实现方案
前端部分(原有HTML代码零修改)
你现有的以下业务代码完全保留,不需要做任何标签、属性、绑定事件的改动:
<input type="file" name="data" id="data" ></input> <button type="button" name="submit" id="submit" onclick="process()">Upload File</button>
只需要补充以下JS逻辑即可:
- 引入reCAPTCHA执行脚本,将参数中的站点密钥替换为你自己申请的公钥
- 初始化时选用隐形模式绑定到你现有的上传按钮,不会改动按钮原有样式和交互
- 改造原有
process()函数逻辑,点击按钮先触发reCAPTCHA校验,拿到校验token后再执行你原有的fetch上传逻辑,把token一并提交给后端
完整JS参考代码:
// 替换为你自己的reCAPTCHA站点公钥 const RECAPTCHA_SITE_KEY = "你的reCAPTCHA站点公钥"; let recaptchaWidgetId; // 页面加载完成后初始化reCAPTCHA window.addEventListener('load', () => { grecaptcha.ready(() => { // 隐形渲染,绑定到现有按钮,不生成额外可见元素 recaptchaWidgetId = grecaptcha.render('submit', { sitekey: RECAPTCHA_SITE_KEY, size: 'invisible', callback: (token) => { // 校验通过拿到token,执行原有上传逻辑 runOriginalUploadProcess(token); } }); }); }); // 原有按钮绑定的process函数保留同名,不需要修改HTML上的onclick绑定 function process() { // 点击按钮先触发人机校验 grecaptcha.execute(recaptchaWidgetId); } // 把你原来写在process里的fetch上传逻辑挪到这个函数即可 function runOriginalUploadProcess(recaptchaToken) { const fileInput = document.getElementById('data'); const uploadFile = fileInput.files[0]; const formData = new FormData(); formData.append('data', uploadFile); // 仅新增这一行,把校验token加入请求参数 formData.append('g-recaptcha-response', recaptchaToken); // 你原来写的fetch请求逻辑完全保留,不需要修改 fetch('你的PHP后端接口地址', { method: 'POST', body: formData }).then(res => res.json()) .then(res => { // 你原来的请求成功、失败处理逻辑 console.log(res); // 请求完成后重置reCAPTCHA,避免token过期影响下次提交 grecaptcha.reset(recaptchaWidgetId); }); }
后端PHP部分
在你原有文件上传处理逻辑的最开头,补充reCAPTCHA token校验逻辑,校验通过再走原有的文件处理流程即可,原有业务代码不需要改动。
参考代码:
<?php // 替换为你自己的reCAPTCHA服务端私钥,不要泄露给前端 $RECAPTCHA_SECRET_KEY = "你的reCAPTCHA服务端私钥"; // 接收前端传的校验token $recaptchaToken = $_POST['g-recaptcha-response'] ?? ''; if (!$recaptchaToken) { header('Content-Type: application/json'); echo json_encode(['code' => 403, 'msg' => '人机校验参数缺失']); exit; } // 向reCAPTCHA服务端发起校验请求 $ch = curl_init('reCAPTCHA官方校验接口地址'); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, [ 'secret' => $RECAPTCHA_SECRET_KEY, 'response' => $recaptchaToken, 'remoteip' => $_SERVER['REMOTE_ADDR'] ]); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $verifyResult = json_decode(curl_exec($ch), true); curl_close($ch); // 校验不通过直接拦截 if (!$verifyResult || !$verifyResult['success']) { header('Content-Type: application/json'); echo json_encode(['code' => 403, 'msg' => '人机校验未通过,请重试']); exit; } // 校验通过,下面完全保留你原有的文件上传、业务处理代码即可 // 原有的文件存储、数据处理逻辑不需要做任何修改 ?>
注意事项
- 选用隐形模式reCAPTCHA不会改变现有页面UI,用户交互流程和改造前完全一致,v3版本还支持无感校验,不会弹出验证框打断用户操作
- 服务端私钥只能存放在PHP后端,绝对不能写到前端代码里
- 每次请求结束后必须调用
grecaptcha.reset()重置组件,否则token有效期过了之后会导致后续提交失败 - 如果需要更高的拦截精度,可以根据reCAPTCHA返回的风险评分调整拦截阈值
内容的提问来源于stack exchange,提问作者TWolfe
相关产品推荐
相关产品推荐

