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

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

问题描述

我正在尝试将看不见的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.

我认为form标记中的(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天全站免登陆