首页 文章

使用Redux表单实现不可见的reCAPTCHA

提问于
浏览
9

我正在尝试使用React和Redux Form实现Invisible reCAPTCHA . 通常,Invisible reCAPTCHA工作流程是:

  • 渲染"invisible" CAPTCHA,返回其小部件ID .

  • 使用小部件的ID调用 grecaptcha.execute . 如有必要,将提示用户解决挑战 . 结果将传递给呈现CAPTCHA时指定的回调函数 .

  • 提交表格和CAPTCHA结果 .

我've created a React component intended to be used with Redux Form' s Field 在调用 grecaptcha.execute 之后呈现CAPTCHA并更新表单状态:

class ReCaptcha extends React.Component {
  render() {
    return <div ref={div => this.container=div} />
  }

  componentDidMount() {
    const { input: { onChange }, sitekey } = this.props
    grecaptcha.render(this.container, {
      sitekey,
      size: "invisible",
      callback: onChange
    })
  }
}

但是,我不知道在用户提交表单时如何或在何处将 grecaptcha.execute 与窗口小部件ID一起调用 . 我无法在 onSubmit 中调用它,因为那里无法访问窗口小部件ID . 我可以在渲染CAPTCHA之后立即在 ReCaptcha 中调用它,但是如果用户需要解决CAPTCHA,则在表单呈现后会立即提示他这样做 .

这个minimal working example显示了我迄今取得的成就 .

3 回答

  • 0

    使用onSubmit prop调用grecaptcha.execute(),并将数据回调指向'real'onSubmit函数 .

    let refToMyWidget;
    const { handleSubmit } = this.props;
    
    componentDidMount() {
      if (window.grecaptcha) {
        refToMyWidget = window.grecaptcha.render(this.container, {
          sitekey: "xxxx",
          size: "invisible",
          callback: handleSubmit(this.actuallySubmit)
        })
      }
    }
    
    preSubmit() {
      if(!window.grecaptcha) {
        return;
      }
      window.grecaptcha.execute(this.refToMyWidget)
    }
    
    actuallySubmit() {
      // submission logic here
    }
    
    render() {
      return (
        <form onSubmit={handleSubmit(this.preSubmit)}>
            <Field name="foo" component="input" />
            <button>Submit</button>
        </form>
      )
    }
    

    注:我没有测试过这段代码,但它应该或多或少是正确的 . 如果您在将grecaptcha加载到页面/表单时遇到问题,我发现this代码非常有用 .

  • 0

    我必须让隐形的reCAPTCHA为我工作,因为可见的reCAPTCHA没有响应 . Here是我实施的例子 .

    首先要做的是在身体上添加下面的标签(或者你可以使用react-helmet) .

    <script src="https://www.google.com/recaptcha/api.js?onload=onloadCallback&render=explicit" async defer></script>
    

    我工作代码的简化版本:

    import React from 'react';
    
    class YourComponent extends React.Component {
      componentDidMount() {
        // Create a script to make sure the reCAPTCHA API is called.
        const script = document.createElement('script');
        script.text = `
          var onloadCallback = function() {
            console.log('grecaptcha is ready');
          };
        `;
        document.body.appendChild(script);
    
        // We will render reCAPTCHA after the page is loaded,
        // because we want to bind our own submit methods.
        window.addEventListener('load', this.onLoad);
      }
    
      // Runs once the form is submitted.
      onRecaptcha = (e) => {
        e.preventDefault();
        const { grecaptcha } = window;
        grecaptcha.execute();
      };
    
      // Real submit function.
      onSubmit = (token) => {
        // I'm not sure what token could be if recaptcha fails.
        // In my case it seems successful and returns a long string.
        console.log(token);
    
        // Your real action goes below...
      };
    
      onLoad = () => {
        // Now we define our reCAPTCHA
        if (window.grecaptcha) {
          const { grecaptcha } = window;
          grecaptcha.render('recaptcha', { // div#recaptcha
            sitekey  : '',
            size     : 'invisible',
            callback : this.onSubmit
          });
        }
      };
    
      render() {
        return (
          <div>
            <Helmet>
              <script
                src="https://www.google.com/recaptcha/api.js?onload=onloadCallback&render=explicit"
                async
                defer
              />
            </Helmet>
            <form onSubmit={this.onRecaptcha}>
              <div id="recaptcha" />
              <button type="submit">Submit</button>
            </form>
          </div>
        );
      }
    }
    
    export default YourComponent;
    
  • 0

    这样你就可以在任何地方实现它

    import React, { Component } from "react";
    
        export default class Test extends Component {
    
          componentWillMount = () => {
            const script = document.createElement("script");
            script.src = "https://www.google.com/recaptcha/api.js";
            script.async = true;
            script.defer = true;
            document.body.appendChild(script);
    
            window.addEventListener("load", this.onLoad);
          };
    
          onLoad = () => {
            if (window.grecaptcha) {
              window.grecaptcha.render("recaptcha", {
                sitekey: "",
                size: "invisible",
                callback: this.onCaptcheCompleted
              });
            }
          };
          onCaptcheCompleted = e => {
            //do what ever you want
            console.log(e);
          };
    
          render() {
            return (
              <div id="recaptcha">
                <input />
                <button onClick={() => window.grecaptcha.execute()} />
              </div>
            );
          }
        }
    

相关问题