Jump to content
Sign in to follow this  
Czar

reCaptcha

Recommended Posts

I am trying to implement a "i am not a robot" into my website

 

Basic HTML/JS looks like the following with a second step required to validate it server side.

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

HTML:

<div class="g-recaptcha" data-sitekey="YOUR_KEY" data-callback="correctCaptcha"></div>

JS:

var correctCaptcha = function(response) {
        alert(response);
    };

I thought I could manage getting it to wok in SMS but I got very lost. I couldn't find examples that seemed to be a parallel challenge.

It would be great to have some clear tutorial or case study to show how it is possible to integrate JS

 

and or it would be good to a have google recaptcha component :)

 

 

info link: https://stackoverflow.com/questions/27902539/how-can-i-validate-google-recaptcha-v2-using-javascript-jquery

https://developers.google.com/recaptcha/intro

Share this post


Link to post
Share on other sites

this is a finnicky api, which needs multiple steps to figure this out.

Step1 : display the captcha widget

It is not just the case of adding the 'https://www.google.com/recaptcha/api.js' file to the index/template file, as it clashes with a standard smart project. Don't know why, something to do with timing

So workaround #1 : read the api file in code (maximum control) and set up a TPanel as the widget control

procedure TForm1.InitializeForm;
begin
  inherited;
  // this is a good place to initialize components
  Var Captcha : TW3Panel := TW3Panel.Create(self);
  Captcha.SetBounds(50, 100, 304+4, 78+4);

  var Script := browserapi.document.createElement('script');
  Script.src := 'https://www.google.com/recaptcha/api.js';

  browserapi.document.head.appendChild(Script);
  Script.onload := procedure
  begin
    writeln('loaded');

    Captcha.innerHTML := #'
      <form action="?" method="POST">
        <div class="g-recaptcha" data-sitekey="6Lf8I...site key ...WY5hq"
                                 data-callback="mycallback"></div>
        <br/>
        <input type="submit" value="Submit">
      </form>
    ';
  end;

end;

The captcha widget is 304 * 78, so we'll embed it in a standard T(W3)Panel.

The innerHtml solution is not very elegant (but works). I'll see if this can be changed to a normal post xmlhttprequest later.

Demo so far

 

Share this post


Link to post
Share on other sites

What I did (for a reset pass form) was to include gogle recapcha js  to html, it auto displays/shows a small recaptcha logo on lower right and shows challenge only when my SMS ResetPass button is pressed:


 

var
  grecaptcha external 'grecaptcha': Variant;

  grecaptcha.execute(GoogleRecaptchaKey, InitObject(['action', 'pwdreset'])).then(
    lambda (token: Variant)
      // We received result from Google recaptcha, pass it along with other entered values to the server
      // Server will perform final validation of received token (is it valid value or not).
      WriteLn(Token);

      glbApp.ResetPass(Trim(edtUserName.value), Trim(edtCust.value),
        lambda (AClient, AStatus)
           ShowMessage('If entered details match registered user, password reset details will be sent to your eMail address.');
        end
      );
    end
  );


 

Share this post


Link to post
Share on other sites

Its actually simpler than I thought - the Google documentation is esoteric at best

  • the reCaptcha widget produces some sort of response when the user clicks the checkbox (g-rechapta-response).
  • This response is POST-sent (either by form or by xmlhttprequest) to a back-end server side script.  
  • this script queries the "https://www.google.com/recaptcha/api/siteverify" url, which gives a response either ok or not ok

This server-side script can be f.i. node.js or php based

In php something like this (recaptchajax.php)

<?php
$secret="6Lf8I....secret key.....BrulLk";
$response=$_POST["captcha"];

$verify=file_get_contents("https://www.google.com/recaptcha/api/siteverify?secret={$secret}&response={$response}");
$captcha_success=json_decode($verify);
if ($captcha_success->success==false) {
  //This user was not verified by recaptcha.
  echo 'false';
}
else if ($captcha_success->success==true) {
  //This user is verified by recaptcha
  echo 'true';
}
?>

and the invocation, with a proper POST xmlhttprequest :

unit Form1;

interface

uses 
  System.Types, System.Types.Convert, System.Objects, System.Time,
  System.IOUtils, System.Device.Storage,
  SmartCL.System, SmartCL.Time, SmartCL.Graphics, SmartCL.Components,
  SmartCL.FileUtils, SmartCL.Device.Storage, SmartCL.Forms, SmartCL.Fonts,
  SmartCL.Theme, SmartCL.Borders, SmartCL.Application, SmartCL.Controls.Panel,
  SmartCL.Net.Http, ECMA.Json, SmartCL.Controls.Button;

type
  TForm1 = class(TW3Form)
  private
    {$I 'Form1:intf'}
  protected
    procedure InitializeForm; override;
    procedure InitializeObject; override;
    procedure Resize; override;
    procedure RetrieveCaptcha(Sender: TW3HttpRequest);
    Button1 : TW3Button;
  end;

var grecaptcha external 'grecaptcha': Variant;

implementation

{ TForm1 }

procedure TForm1.InitializeForm;
begin
  inherited;
  // this is a good place to initialize components
  Var Captcha : TW3Panel := TW3Panel.Create(self);
  Captcha.SetBounds(50, 100, 304+4, 78+4);

  Button1 := TW3Button.Create(self);
  Button1.SetBounds(50, 200, 100, 30);
  Button1.Caption := 'submit';

  var Script := browserapi.document.createElement('script');
  Script.src := 'https://www.google.com/recaptcha/api.js';

  browserapi.document.head.appendChild(Script);
  Script.onload := procedure
  begin
    Captcha.innerHTML := '<div class="g-recaptcha" data-sitekey="6Lf8I6....site key.....WY5hq"></div>';

    Button1.onclick := procedure(sender:TObject) begin
      var FHttp := TW3HttpRequest.Create;
      FHttp.OnDataReady := RetrieveCaptcha;
      FHttp.open("POST","https://www.lynkfs.com/Experiments/reCaptcha/www/lib/recaptchajax.php");
      FHttp.RequestHeaders.Add("Content-type","application/x-www-form-urlencoded");
      var mycaptcha := "captcha=" +grecaptcha.getResponse();
      FHttp.send(mycaptcha);
    end;

  end;
end;

procedure TForm1.RetrieveCaptcha(Sender: TW3HttpRequest);
begin
  writeln(JSON.parse(Sender.ResponseText));             //console : either 'true' or 'false'
  If JSON.parse(Sender.ResponseText) = true  then Button1.Caption := 'OK';
  If JSON.parse(Sender.ResponseText) = false then Button1.Caption := 'Spam';
end;

procedure TForm1.InitializeObject;
begin
  inherited;
  {$I 'Form1:impl'}
end;
 
procedure TForm1.Resize;
begin
  inherited;
end;
 
initialization
  Forms.RegisterForm({$I %FILE%}, TForm1);
end.

Demo url as before

 

Share this post


Link to post
Share on other sites

as @IgorSavkic pointed out, there are many options and use cases for this api. 

I think this is the most common one. 

The funny thing is that even doing only step 1 (displaying the widget with the selection of pictures of bridges, buses etc) and not even doing step 2 (the back-end check) gives some kind of spammer protection. 

I suspect quite a few websites do it that way

Share this post


Link to post
Share on other sites

Yes, without the backend check it is nothing. I am only putting it on our page becuase of one person's concerns about spammers :)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×