Jump to content

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

Link to post
Share on other sites
  • Moderators

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

 

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


 

Link to post
Share on other sites
  • Moderators

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

 

Link to post
Share on other sites
  • Moderators

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

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...