You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

集成reCAPTCHA v3的React应用能否阻止爬虫获取未渲染内容

}

我的`index.js`代码如下:
```js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import './i18n';
import reportWebVitals from './reportWebVitals';
import {GoogleReCaptchaProvider} from 'react-google-recaptcha-v3';
import {ValidationRecaptcha} from "./components/reCaptcha";

ReactDOM.render(
    <React.StrictMode>
        <GoogleReCaptchaProvider reCaptchaKey={process.env.REACT_APP_RECAPTCHA_PUBLIC_KEY}>
            <ValidationRecaptcha/>
        </GoogleReCaptchaProvider>
    </React.StrictMode>,
    document.getElementById('root')
);

reportWebVitals();

以下是ValidationRecaptcha组件的代码:

import React, {useCallback, useEffect, useState} from "react";
import {useGoogleReCaptcha} from "react-google-recaptcha-v3";
import App from "../App";
import {PuffLoader} from "react-spinners";

export const ValidationRecaptcha = () => {
    const { executeRecaptcha } = useGoogleReCaptcha();
    const [verified, setVerified] = useState(0);
    const handleReCaptchaVerify = useCallback(async () => {

        if (!executeRecaptcha) {
            console.log('Execute recaptcha not yet available');
            return;
        }

        console.log('Request token from Google...');
        const token = await executeRecaptcha('token');
        console.log('Received token from Google: ' + token);

        function handleReCaptchaResponse(success) {
            setVerified(success ? 2 : 1);
        }

        // check the token with the backend
        const url = process.env.REACT_APP_BACKEND_API_URL + "/recaptcha?token=" + token.toString();
        console.log('Request token verification from backend: ' + url);
        fetch(url)
            .then((res) => res.json())
            .then((data) => handleReCaptchaResponse(JSON.parse(data.success)));
        console.log('Answer from API: success = ' + verified);

    }, [executeRecaptcha, verified]);

    // use useEffect to trigger the verification as soon as the component being loaded
    useEffect(() => {
        handleReCaptchaVerify();
    }, [handleReCaptchaVerify]);

    let content;
    if (verified === 0) {
        content = <div><div className={'center'}><PuffLoader/></div><div className={'center-horizontally'}>Checking your browser with Google reCAPTCHA v3...</div></div>;
    } else if (verified === 1) {
        content = <div className={'center'}>Sorry, looks like you're a Robot 🤖. This site is humans-only!</div>;
    } else {
        content = <App/>;
    }
    return content;
};

简要说明

代码在浏览器中运行符合预期,我已经测试了Chrome、Safari和Firefox浏览器。等待验证请求返回时,应用会渲染verified === 0对应的加载内容;如果验证不通过(token无效或者reCAPTCHA判定为爬虫),应用会渲染verified === 1的拦截内容;如果验证通过,就会渲染<App/>组件,包含所有功能、静态内容(比如备案信息里的邮箱、电话、地址)和联系表单。

我的问题

  1. 这个方案是否合理?爬虫(比如专门爬取网站信息的垃圾爬虫)能不能直接获取所有JSX文件,拿到<App/>及其子组件里的个人数据比如邮箱、电话、地址? 我手动测试无效token或者低评分的情况时,Chrome的开发者工具里只能看到当前渲染的内容,搜索邮箱也没有结果,而这个邮箱是明文写在<App/>的子组件里的;只有验证通过的时候才能在源文件里搜索到邮箱内容。
  2. 我能不能认为React应用只会对外暴露运行时需要渲染的文件?
  3. 和第一个问题本质一致,就是确认我的认知:这个方案能不能保护深层的联系表单不被垃圾爬虫提交,还是说我在向SMTP服务发数据前还要再做一次校验?

我觉得这些问题是因为我对React的运行机制了解不够,如果有相关的入门资料也麻烦推荐。
祝好
maximotus


回答

问题1解答

这个方案完全不合理,垃圾爬虫完全可以拿到你所有的前端静态资源内容。
你在Chrome元素面板看不到未验证状态下的App组件内容,只是因为元素面板只展示当前已渲染到DOM树的内容,但你所有的React代码(包括App及其所有子组件内容)在执行npm run build后,都会被打包成一个或多个JS bundle静态文件。这些文件默认是公开可访问的,爬虫根本不需要走前端的reCAPTCHA验证逻辑,直接请求打包后的JS文件地址,就能拿到所有硬编码在代码里的邮箱、电话等信息。你可以在未验证的状态下直接访问你站点的打包后JS文件,直接搜索邮箱关键词,大概率能直接搜到对应内容。

问题2解答

绝对不能这么认为。
React是客户端渲染框架,所有打包后的静态资源默认都存放在web服务器的公开可访问目录下,和你前端渲染什么内容没有任何关系。前端的条件渲染只是控制内容要不要展示到DOM里,完全不会阻止静态资源本身被下载,只要爬虫能拿到资源链接,就能下载完整的bundle文件,解析出里面所有的明文内容。

问题3解答

不能,你必须在后端对所有表单提交请求做reCAPTCHA校验,前端的所有校验逻辑都可以被绕过。
不管你前端的verified状态是啥,爬虫完全可以跳过你的前端验证逻辑,直接往表单提交接口发请求。所以后端必须对每一次表单提交请求携带的reCAPTCHA token做校验,校验通过才允许调用SMTP发邮件,前端的任何拦截逻辑都只能防君子不防小人。

补充建议

如果你真的要保护硬编码的敏感静态内容,不要把这些内容写在前端代码里,应该放在后端,只有前端通过reCAPTCHA验证之后,再从后端接口请求这些敏感内容再渲染到页面上,这样爬虫就算拿到了前端bundle,也找不到硬编码的敏感信息。
如果要深入理解React的客户端渲染原理,可以看React官方文档的主概念部分,跟着基础教程走一遍就能搞清楚打包和运行的基本逻辑。


内容的提问来源于stack exchange,提问作者maximotus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 11:15:03