Angular Basic CAPTCHA Code Example

Please Note

Angular Captcha Module requires the new experimental Simple API that is currently available only in BotDetect Java version (4.0.Beta3+). Click here to find out when the Simple API will be available in BotDetect ASP.NET, PHP, and Classic ASP.

  1. Client-side
    1. AngularJS 1.x
    2. Angular 2+
  2. Server-side

I. Client-side

a) AngularJS 1.x

The AngularJS Basic Captcha code example shows the most basic source code required to protect an AngularJS application with BotDetect CAPTCHA and validate the user input.

It can be used as a starting point when you first learn how to use BotDetect in your AngularJS application.

Download the BotDetect Java CAPTCHA Library and run this example

Downloaded Location

The AngularJS Basic CAPTCHA code example is included in the examples/simple-api/bdc4-simple-api-angularjs-captcha-example.war file of the download package. When deploying (unpacking) the file you will see the following main source code files:

basic-captcha.html

<form name="basicForm" novalidate ng-controller="BasicController" ng-submit="validate(basicForm.$valid)">

  <div class="alert alert-success" ng-show="successMessages">
    {{ successMessages }}
  </div>

  <div class="alert alert-error" ng-show="errorMessages">
    {{ errorMessages }}
  </div>

  <!-- show Captcha image html-->
  <botdetect-captcha styleName="angularBasicCaptcha"></botdetect-captcha>

  <label>
    <span>Retype the characters from the picture:</span>
    <!-- captcha code user input textbox -->
    <input type="text" name="captchaCode" ng-model="captchaCode" correct-captcha id="captchaCode" autocomplete="off">
  </label>


  <div class="error" ng-show="basicForm.captchaCode.$invalid && !basicForm.captchaCode.$pristine">
    Incorrect code.
  </div>

  <button type="submit" ng-disabled="basicForm.$invalid">Validate</button>
</form>

Adding Captcha protection to the AngularJS form is as simple as using botdetect-captcha element, which is provided by BotDetect Captcha AngularJS Module and set to styleName attribute a Captcha style name defined in botdetect.xml configuration file below.

We have used correct-captcha directive attribute in captcha code input field to perform UI Captcha validation on blur event.

To display captcha error message, we simply check $invalid of captchaCode. If it returns true, this means that UI captcha validation failed.

app.js

var app = angular.module('app', ['BotDetectCaptcha']);

app.config(function(captchaSettingsProvider) {
  captchaSettingsProvider.setSettings({
    captchaEndpoint: '/bdc4-simple-api-angularjs-captcha-example/botdetectcaptcha'
  });
});

app.controller('BasicController', function($scope, $http, Captcha) {

  // captcha validation messages
  $scope.successMessages = '';
  $scope.errorMessages = '';
  
  // basic captcha url
  var basicUrl = '/bdc4-simple-api-angularjs-captcha-example/basic-captcha';
  
  $scope.validate = function(valid) {

    if (!valid) {
      return;
    }
    
    // after UI form validation passed, 
    // we will need to validate captcha at server-side once before we save form data in database, etc.
    
    // create new BotDetect Captcha instance
    var captcha = new Captcha();
    
    // captcha id for validating captcha at server-side
    var captchaId = captcha.captchaId;
    
    // captcha code input value for validating captcha at server-side
    var captchaCode = $scope.captchaCode;

    var postData = {
      captchaId: captchaId,
      captchaCode: captchaCode
    };
    
    $http({
      method: 'POST',
      url: basicUrl,
      data: JSON.stringify(postData)
    })
      .then(function(response) {
        if (response.data.success) {
          // captcha validation passed at server-side
          $scope.successMessages = 'CAPTCHA validation passed.';
          $scope.errorMessages = null;
        } else {
          // captcha validation falied at server-side
          $scope.errorMessages = 'CAPTCHA validation falied.';
          $scope.successMessages = null;
        }
        
        // always reload captcha image after validating captcha at server-side 
        // in order to update new captcha code for current captcha id
        captcha.reloadImage();
      }, function(error) {
        console.log(error.data);
      });
  };
   
});

First, we add BotDetectCaptcha to the app module as a dependency and configure BotDetect Java Captcha path to captchaEndpoint settings in config function.

In the code above, we inject Captcha into BasicController.

To validate Captcha code once at server-side api, we need to send captchaId property of Captcha object and captcha code visitors submitted to server-side.

Once request finished, we always reload Captcha by calling reloadImage() function of Captcha object. This is needed to generate the new captcha code for the current captcha id.

b) Angular 2+

The Angular Basic Captcha code example shows the most basic source code required to protect an Angular application with BotDetect CAPTCHA and validate the user input.

It can be used as a starting point when you first learn how to use BotDetect in your Angular application.

Download the BotDetect Java CAPTCHA Library and run this example

Downloaded Location

The Angular Basic CAPTCHA code example is included in the examples/simple-api/bdc4-simple-api-angular-captcha-example.war file of download package. When deploying (unpacking) the file you will see the following main source code files:

app.module.ts

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';

import { AppRoutingModule } from './app-routing.module';
import { BotDetectCaptchaModule } from 'angular-captcha';

import { AppComponent } from './app.component';
import { BasicComponent }   from './basic/basic.component';

import { ValuesPipe } from './values.pipe';

@NgModule({
  imports: [
    BrowserModule,
    FormsModule,
    HttpModule,
    AppRoutingModule,
    BotDetectCaptchaModule.forRoot({
      captchaEndpoint: '/bdc4-simple-api-angular-captcha-example/botdetectcaptcha',
    })
  ],
  declarations: [
    AppComponent,
    BasicComponent,
    ValuesPipe
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

We import BotDetectCaptchaModule, then declare it in metadata imports of NgModule and configure BotDetect Java Captcha path in captchaEndpoint settings.

basic.component.html

<form novalidate #f="ngForm" (ngSubmit)="validate(f.value, f.valid)">

  <div class="alert alert-success" *ngIf="successMessages">
    {{ successMessages }}
  </div>

  <div class="alert alert-error" *ngIf="errorMessages">
    {{ errorMessages }}
  </div>

  <!-- show captcha html -->
  <botdetect-captcha styleName="angularBasicCaptcha"></botdetect-captcha>  

  <label>
    <span>Retype the characters from the picture:</span>
    <input
      type="text"
      id="captchaCode"
      name="captchaCode"
      ngModel
      #captchaCode="ngModel"
      correctCaptcha
      >
  </label>

  <div
    class="error"
    *ngIf="captchaCode.errors?.incorrectCaptcha && !captchaCode.pristine"
    >
    Incorrect code.
  </div>

  <button type="submit" [disabled]="f.invalid">Validate</button>
</form>

Adding Captcha protection to the Angular form is as simple as using botdetect-captcha element, which is provided by BotDetect Captcha Angular Module and set to styleName attribute a Captcha style name defined in botdetect.xml configuration file below.

we have used correctCaptcha directive attribute in captcha code input field to perform UI Captcha validation on blur event.

To display captcha error message, you simply check if incorrectCaptcha property exists in captchaCode.errors object. If it exists, this means that UI captcha validation failed.

basic.component.ts

import { Component, ViewChild } from '@angular/core';
import { Observable } from 'rxjs/Rx';

import { CaptchaComponent } from 'angular-captcha';

import { BasicService } from './basic.service';

@Component({
  moduleId: module.id,
  selector: 'basic-form',
  templateUrl: 'basic.component.html',
  styleUrls: ['basic.component.css'],
  providers: [BasicService]
})
export class BasicComponent {

  /**
   * Captcha validation messages.
   */
  errorMessages: string;
  successMessages: string;

  /**
   * BotDetect CAPTCHA component.
   */
  @ViewChild(CaptchaComponent) captchaComponent: CaptchaComponent;

  constructor(private basicService: BasicService) { }

  /**
   * Validate captcha at server-side.
   */
  validate(value, valid): void {

    if (!valid) {
      return;
    }

    const postData = {
      captchaCode: value.captchaCode,
      captchaId: this.captchaComponent.captchaId
    }
  
    this.basicService.validateCaptcha(postData)
      .subscribe(
        response => {
          if (response.success) {
            // captcha, other form data passed and the data is also stored in database
            this.successMessages = 'Your message was sent successfully!';
            this.errorMessages = '';
          } else {
            // captcha validation falied at server-side
            this.errorMessages = 'CAPTCHA validation falied.';
            this.successMessages = '';
          }

          // always reload captcha image after validating captcha at server-side 
          // in order to update new captcha code for current captcha id
          this.captchaComponent.reloadImage();
        },
        error => {
          throw new Error(error);
        });
  }

}

In this component, we inject CaptchaComponent into BasicComponent using @ViewChild.

To validate Captcha code once at server-side api, we need to send captchaId property of CaptchaComponent and captcha code visitors submitted to server-side.

Once request finished, we always reload Captcha by calling the reloadImage() function of CaptchaComponent. This is needed to generate the new captcha code for the current captcha id.

basic.service.ts

import { Injectable }    from '@angular/core';
import { Http, Response, Headers, RequestOptions } from '@angular/http';

import { Observable } from 'rxjs/Rx';

@Injectable()
export class BasicService {

  // basic api url
  basicUrl = '/bdc4-simple-api-angular-captcha-example/basic-captcha';

  constructor(private http: Http) { }

  validateCaptcha(data: Object): Observable<any> {
    const headers = new Headers({ 'Content-Type': 'application/json' });
    const options = new RequestOptions({ headers: headers });

    return this.http.post(this.basicUrl, data, options)
      .map((response: Response) => response.json())
      .catch((error:any) => Observable.throw(error.json().error));
  }
}

In this BasicService, we simply add a function that posts data to the basic api url using Http post of HttpModule.

II. Server-side

botdetect.xml

<?xml version="1.0" encoding="UTF-8"?>
<botdetect xmlns="https://captcha.com/schema/java" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="https://captcha.com/schema/java 
      https://captcha.com/schema/java/botdetect-4.0.beta3.xsd">

  <captchaStyles>
    <captchaStyle>
      <name>angularBasicCaptcha</name>
      <userInputID>captchaCode</userInputID>
      <codeLength>3-5</codeLength>
    </captchaStyle>
  </captchaStyles>

</botdetect>

In WEB-INF/botdetect.xml, we configure some captcha options for our angular basic captcha. You can find a full list of available Captcha configuration options and related instructions at the Captcha configuration options page.

BasicServlet.java

package com.captcha.botdetect.examples.angular.basic_form;

import com.captcha.botdetect.web.servlet.SimpleCaptcha;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class BasicServlet extends HttpServlet {

  @Override
  protected void doPost(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
   
    PrintWriter out = response.getWriter();
    Gson gson = new Gson();
    
    response.setContentType("application/json; charset=utf-8");
    
    
    JsonParser parser = new JsonParser();
    JsonObject formDataObj = (JsonObject) parser.parse(request.getReader());
    
    String captchaId = formDataObj.get("captchaId").getAsString();
    String captchaCode = formDataObj.get("captchaCode").getAsString();
    
    // validate captcha
    SimpleCaptcha captcha = SimpleCaptcha.load(request);
    boolean isHuman = captcha.validate(captchaCode, captchaId);
    
    if (isHuman) {
      // Captcha validation passed
      // TODO: do whatever you want here
    }
    
    // the object that stores validation result
    BasicValidationResult validationResult = new BasicValidationResult();
    validationResult.setSuccess(isHuman);
    
    try {
      // write the validation result as json string for sending it back to client
      out.write(gson.toJson(validationResult));
    } catch(Exception ex) {
      out.write(ex.getMessage());
    } finally {
      out.close();
    }
  }
}

At server-side api, we will get captchaId and captchaCode values sent from client-side and use validate(captchaCode, captchaId) method of SimpleCaptcha instance to validate Captcha code. Finally, we write the validation result as json string for sending it back to client.

BasicValidationResult.java

package com.captcha.botdetect.examples.angular.basic_form;

public class BasicValidationResult {
  private boolean success;

  public BasicValidationResult() {
  }

  public boolean getSuccess() {
    return success;
  }

  public void setSuccess(boolean success) {
    this.success = success;
  }
}

This class is to store Captcha validation result and use it to convert to JSON string using Gson library in BasicServlet.