Sitecore 9 Forms: Google reCaptcha field
Re-Captcha is the most important part of any form’s submission. Google reCaptcha run internet bot detector and determined whether a user is a bot or not.
Sitecore Forms does not provide Google reCaptcha field, which was available in WFFM before, so I have created my custom Google reCaptcha.
Below you can find step by step process to create Google reCaptcha field.
- Create patch config for reCaptcha Sitekey and SecretKey
<?xml version="1.0"?>
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/" xmlns:set="http://www.sitecore.net/xmlconfig/set/">
<sitecore>
<settings>
<setting name="ReCaptchaSiteKey" value="site-key" />
<setting name="ReCaptchaSecretKey" value="secret-key" /> </settings>
</sitecore>
</configuration>
- Create new viewmodel class RecaptchaViewModel.cs
[Serializable()] public class RecaptchaViewModel : MultipleLineTextViewModel { public string SiteKey { get; set; } public string SecretKey { get; set; } public string Message { get; set; } protected override void InitItemProperties(Item item) { base.InitItemProperties(item); string GoogleSiteKey = Configuration.Settings.GetSetting("ReCaptchaSiteKey"); string GoogleSecretKey = Configuration.Settings.GetSetting("ReCaptchaSecretKey"); if (!string.IsNullOrEmpty(GoogleSiteKey) && !string.IsNullOrEmpty(GoogleSecretKey)) { SiteKey = GoogleSiteKey; SecretKey = GoogleSecretKey; } } }
- Create new CustomRecaptcha.cshtml file on this location “Website/Views/FormBuilder/FieldTemplates”
@model <Path>.RecaptchaViewModel
<script src='https://www.google.com/recaptcha/api.js'></script>
<script>
$(document).ready(function () {
$('.recaptcha').click(function (e) {
var recaptchaResponse = grecaptcha.getResponse();
console.log(recaptchaResponse);
console.log(recaptchaResponse.length);
if (recaptchaResponse.length != 0) {
$('.googleRecaptchaClass').val(recaptchaResponse);
}
})
});
</script>
<span class="msg-error"></span>
<textarea id="@Html.IdFor(m => Model.Value)" class="googleRecaptchaClass" style="display:none;" name="@Html.NameFor(m => Model.Value)" data-sc-tracking="@Model.IsTrackingEnabled" data-sc-field-name="@Model.Name"></textarea>
<div class="g-recaptcha" data-sitekey="@Model.SiteKey"></div>
- In the Sitecore Content Editor, navigate to /sitecore/templates/System/Forms/Fields
- Then add new template with name “CustomRecaptcha” and select Base template /sitecore/templates/System/Templates/Template
- You can inherit template which is required
- Switch to Core DB and create copy of this item “sitecore/client/Applications/FormsBuilder/Components/Layouts/PropertyGridForm/PageSettings/Settings/SingleLineText” with name “CustomRecaptcha”
- Now move again to Master DB.
- Create new Field type here “/sitecore/system/Settings/Forms/Field Types/Security” with name “CustomRecaptcha”
- Fill below details:
- View Path: FieldTemplates/CustomRecaptcha
- Model Type: <Namespace>. RecaptchaViewModel, <AssemblyName>
- Property Editor: Property Editor Settings/CustomRecaptcha
- Field Template: Fields/CustomRecaptcha
Custom reCaptcha Validation
- Create new submit action class RecaptchaValidate
public class RecaptchaValidate : SubmitActionBase<string> { /// <summary> /// Initializes a new instance of the <see cref="LogSubmit"/> class. /// </summary> /// <param name="submitActionData">The submit action data.</param> public RecaptchaValidate(ISubmitActionData submitActionData) : base(submitActionData) { } /// <summary> /// Tries to convert the specified <paramref name="value" /> to an instance of the specified target type. /// </summary> /// <param name="value">The value.</param> /// <param name="target">The target object.</param> /// <returns> /// true if <paramref name="value" /> was converted successfully; otherwise, false. /// </returns> protected override bool TryParse(string value, out string target) { target = string.Empty; return true; } /// <summary> /// Executes the action with the specified <paramref name="data" />. /// </summary> /// <param name="data">The data.</param> /// <param name="formSubmitContext">The form submit context.</param> /// <returns> /// <c>true</c> if the action is executed correctly; otherwise <c>false</c> /// </returns> protected override bool Execute(string data, FormSubmitContext formSubmitContext) { if (!formSubmitContext.HasErrors) { RecaptchaViewModel googleRecaptchaFieldValue = formSubmitContext.Fields.Where(x => x is RecaptchaViewModel).FirstOrDefault() as RecaptchaViewModel; if (googleRecaptchaFieldValue != null) { ISitecoreContext sitecoreContext = ServiceLocator.ServiceProvider.GetService<ISitecoreContext>(); var formSettings = sitecoreContext.GetItem<_FormSettings>(ItemIds.FormSettings); if (formSettings != null && !string.IsNullOrEmpty(formSettings.SecretKey)) { bool isCapthcaValid = ValidateCaptcha(googleRecaptchaFieldValue.Value, formSettings.SecretKey.ToString()); try { if (isCapthcaValid) { return true; } } catch { formSubmitContext.Abort(); return false; } } } formSubmitContext.Abort(); return false; } else { Logger.Warn(Invariant($"Form {formSubmitContext.FormId} submitted with errors: {string.Join(", ", formSubmitContext.Errors.Select(t => t.ErrorMessage))}."), this); } formSubmitContext.Abort(); return false; } public static bool ValidateCaptcha(string response, string secret) { string RecaptchaUrl = Configuration.Settings.GetSetting("GoogleApi"); var client = new WebClient(); var reply = client.DownloadString(RecaptchaUrl+"?secret=" + secret + "&response="+response); var captchaResponse = JsonConvert.DeserializeObject<CaptchaResponse>(reply); return System.Convert.ToBoolean(captchaResponse.Success); } }
<?xml version="1.0"?>
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/" xmlns:set="http://www.sitecore.net/xmlconfig/set/">
<sitecore>
<settings>
<setting name="GoogleApi" value="https://www.google.com/recaptcha/api/siteverify"/>
</settings>
</sitecore>
</configuration>
public class CaptchaResponse
{
[JsonProperty("success")]
public bool Success { get; set; }
[JsonProperty("error-codes")]
public List<string> ErrorMessage { get; set; }
}
- Model Type: <Path>.RecaptchaValidate
- Error Message: Invalid Captcha
- Drag and drop control into your form
- Do not forget to select “Recaptcha Validate” on your submit action
- Render form into your page and Enjoy
Comments
I am trying to implement Google ReCaptcha V3
I was able to implement following these steps. But I am facing just one issue. My Custom Submit Method is called twice and thus it results duplicate ReCaptcha verification.
I have placed by Custom Submit item before Save Data in the Forms design.
Could you please let me know what can be the issue? Any hints or response is much appreciated. Thank you.