【问题标题】:Implementing Invisible reCAPTCHA with Redux Form使用 Redux Form 实现 Invisible reCAPTCHA
【发布时间】:2017-02-10 01:40:44
【问题描述】:

我正在尝试使用 React 和 Redux Form 实现 Invisible reCAPTCHA。一般来说,Invisible reCAPTCHA 工作流程是:

  1. 呈现“不可见”的验证码,返回其小部件 ID。
  2. 使用小部件的 ID 调用 grecaptcha.execute。如有必要,将提示用户解决挑战。结果将传递给在呈现验证码时指定的回调函数。
  3. 连同验证码结果一起提交表单。

我创建了一个 React 组件,旨在与 Redux Form 的 Field 一起使用,它呈现 CAPTCHA 并在调用 grecaptcha.execute 后更新表单状态:

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 展示了我到目前为止所取得的成就。

【问题讨论】:

    标签: reactjs recaptcha redux-form


    【解决方案1】:

    使用 onSubmit 属性调用 grecaptcha.execute(),并将数据回调指向“真正的”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 代码非常有用。

    【讨论】:

      【解决方案2】:

      我不得不让不可见的 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;
      

      【讨论】:

      • 我发现使用scriptjs 库要容易得多。如果你愿意,我会举一个例子。
      【解决方案3】:

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

      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>
              );
            }
          }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-06-29
        • 2017-08-25
        • 2017-08-02
        • 1970-01-01
        相关资源
        最近更新 更多