将 reCAPTCHA 与 Angular 4 集成的正确方法 [英] Correct way to integrate reCAPTCHA with Angular 4

查看:52
本文介绍了将 reCAPTCHA 与 Angular 4 集成的正确方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将 Invisible reCAPTCHA 与我的 Angular 4 表单集成.

I'm trying to integrate an Invisible reCAPTCHA with my Angular 4 form.

在组件的 TS 部分,我有一个这样的功能:

In the TS part of the component I have a function like this:

onSubmit(token: string) {
    alert(token);
}

我的 HTML 如下所示(仅显示相关部分):

And my HTML looks like this (only the relevant parts shown):

<form (ngSubmit)="onSubmit()" #myForm="ngForm">
    <button  type="submit" class="btn g-recaptcha" data-sitekey="mykey" data-callback="onSubmit">Submit</button>
</form>

单击该按钮时,我收到一条警告,指出令牌未定义,或者收到如下错误消息:无法联系 reCAPTCHA.请检查您的连接,然后重试."不是真正的确定性 - 有时我会看到一种行为,有时会看到另一种.

When clicking on that button I get either an alert saying the token is undefined, or I get an error message like this: "Cannot contact reCAPTCHA. Check your connection and try again." Not really deterministic - sometimes I see one behavior, sometimes the other.

我认为表单标签中的 (ngSubmit) 可能会干扰 reCAPTCHA.但是如果我删除 (ngSubmit) 那么 onSubmit 函数根本不会被调用......

I thought that maybe the (ngSubmit) in the form tag could interfere with the reCAPTCHA. But if I remove (ngSubmit) then the onSubmit function is not called at all...

集成此功能的正确方法是什么?

What is the correct way for integrating this?

AngularJS StackOverflow 上有一个类似的问题,但我没有我真的不知道如何将该解决方案应用于 Angular 4.

There is a similar question for AngularJS here on StackOverflow, but I don't really know how to adapt that solution to Angular 4.

推荐答案

ReCAPTCHA 可以在 Angular 中实现如下.请注意,此示例不包含所需的服务器端代码.

ReCAPTCHA may be implemented in Angular as follows. Note that this example does not include the required server-side code.

包括reCAPTCHA api.

<script src="https://www.google.com/recaptcha/api.js" async defer></script>

声明 ReCAPTCHA

ReCAPTCHA 变量可以在 Typescript 中声明如下:

Declare ReCAPTCHA

The ReCAPTCHA variable may be declared in Typescript as follows:

declare var grecaptcha: any;

然而,为了更多的类型支持,可以使用接口ReCAPTCHA.

However, for more type support, the interface ReCAPTCHA may be used.

declare var grecaptcha: ReCAPTCHA;

ReCAPTCHA 接口 (v2) [recaptcha.ts]

import { ElementRef } from '@angular/core';

/**
 * Interface for Google's reCAPTCHA JavaScript API. 
 * 
 * Display API
 * @see {@link https://developers.google.com/recaptcha/docs/display}
 * 
 * Invisible API
 * @see {@link https://developers.google.com/recaptcha/docs/invisible}
 */
export interface ReCAPTCHA {

  /**
   * Programatically invoke the reCAPTCHA check. Used if the invisible reCAPTCHA is on a div 
   * instead of a button.
   * 
   * @param {string} opt_widget_id Optional widget ID, defaults to the first widget created if 
   *     unspecified.
   */
  execute(opt_widget_id?: string): void;

  /** 
   * Renders the container as a reCAPTCHA widget and returns the ID of the newly created widget.
   * 
   * @param {ElementRef|string} container The HTML element to render the reCAPTCHA widget.  Specify 
   *    either the ID of the container (string) or the DOM element itself. 
   * @param {Object} parameters An object containing parameters as key=value pairs, for example,
   *    {"sitekey": "your_site_key", "theme": "light"}.
   */
  render(container: ElementRef|string, parameters: {[key: string]: string}): void;

  /** 
   * Resets the reCAPTCHA widget.
   * 
   * @param {string} opt_widget_id Optional widget ID, defaults to the first widget created if 
   *     unspecified.
   */
  reset(opt_widget_id?: string): void;

  /** 
   * Gets the response for the reCAPTCHA widget. Returns a null if reCaptcha is not validated. 
   * 
   * @param {string} opt_widget_id Optional widget ID, defaults to the first widget created if 
   *     unspecified.
   */
  getResponse(opt_widget_id?: string): string;
}


import { Injectable, OnInit } from '@angular/core'
import { HttpClient, HttpErrorResponse, HttpHeaders, HttpParams, HttpResponse } from '@angular/common/http'
import { Observable } from 'rxjs'
import { map } from 'rxjs/operators'

export interface ReCAPTCHAResponse {
  success: boolean; 
  status_code: number,
  error_codes?: Array<string>;
}

const httpOptions = {
  headers: {'Content-Type': 'application/json'},
  observe: "body",
  responseType: "json",
  withCredentials: true
}


@Injectable()
export class ReCAPTCHAService {
  public constructor(private http: HttpClient) {}

  public verifyUserResponse(userResponseToken: string): Observable<ReCAPTCHAResponse> {
    return this.http.post<ReCAPTCHAResponse>('/auth/captcha', {'g-recaptcha-response': userResponseToken}, httpOptions).
      pipe(map( (resp: HttpResponse) => { ... resp.body }))
  } 
}


import { Component, OnDestroy, OnInit } from '@angular/core'
import { ReCAPTCHA } from './recaptcha'
import { ReCAPTCHAResponse, ReCAPTCHAService } from './recaptcha.service'


declare var grecaptcha: ReCAPTCHA;
declare var window: any;

@Component ({
  moduleId: module.id,
  selector: 'create-account',
  templateUrl: 'create-account.component.html'
})
export class CreateAccountComponent implements OnDestroy, OnInit {

  public constructor(private recaptcha: ReCAPTCHAService) {}

  public ngOnInit(): void {
    // Export reCAPTCHACallback to global scope.
    window['reCAPTCHACallback'] = this.reCAPTCHACallback.bind(this);

    grecaptcha.render('create-account-captcha', {
      'sitekey': 'your-site-key',
      'size': 'invisible',        // Optional (see docs)
      'callback': 'reCAPTCHACallback'
    });
  }

  /**
   * Verify reCAPTCHA response on server. 
   */
  public reCAPTCHACallback(token: string) {
    if (token == null || token.length === 0) {
      grecaptcha.reset();
      // TODO: report that captcha was invalid
    } else {
      this.recaptcha.verifyUserResponse(token).subscribe(
        (r: ReCAPTCHAResponse) => {
          if (r.success) {
            // TODO: create the new user account
          } else {
            grecaptcha.reset();
            // TODO: report that captcha was invalid
          }
        },
        (error: any) => {
          // TODO: handle server error
        }
      })
  }
}

组件模板

<!-- Invisible reCAPTCHA dynamically rendered. -->
<div id='create-account-captcha' class="g-recaptcha"></div>

这篇关于将 reCAPTCHA 与 Angular 4 集成的正确方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆