Skip to content

Instantly share code, notes, and snippets.

@AaronSadlerUK
Last active May 18, 2021 11:19
Show Gist options
  • Save AaronSadlerUK/b0cf5bc55a7df2e86602f53a19e2dfbd to your computer and use it in GitHub Desktop.
Save AaronSadlerUK/b0cf5bc55a7df2e86602f53a19e2dfbd to your computer and use it in GitHub Desktop.
hCaptcha Service for use with a Surface Controller or any MVC Controller (With light modifications)
public class AnySurfaceController : SurfaceController
{
private readonly IhCaptchaService _hCaptchaService;
public AnySurfaceController(IhCaptchaService hCaptchaService)
{
_hCaptchaService = hCaptchaService;
}
[ValidateAntiForgeryToken]
[HttpPost]
public async Task<ActionResult> FormPost(FormModel order)
{
var request = Request;
var valid = _hCaptchaService.Validate(request.UserHostAddress, request.Form["h-captcha-response"]);
if (!valid)
{
ModelState.AddModelError("hCaptcha", "You did not pass the human validation, please try again");
return CurrentUmbracoPage();
}
return CurrentUmbracoPage();
}
}
public static class AppSettingsManager
{
public static string hCaptchaSiteKey()
{
if (ConfigurationManager.AppSettings["hCaptchaSiteKey"] != null)
return ConfigurationManager.AppSettings["hCaptchaSiteKey"];
throw new Exception("\"hCaptchaSiteKey\" is missing in AppSettings.");
}
public static string hCaptchaSecretKey()
{
if (ConfigurationManager.AppSettings["hCaptchaSecretKey"] != null)
return ConfigurationManager.AppSettings["hCaptchaSecretKey"];
throw new Exception("\"hCaptchaSecretKey\" is missing in AppSettings.");
}
}
public class hCaptchaComposer : IUserComposer
{
public void Compose(Composition composition)
{
composition.Register<IhCaptchaService, hCaptchaService>(Lifetime.Request);
}
}
public class hCaptchaService : IhCaptchaService
{
public bool Validate(string remoteIp, string responseText)
{
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/x-www-form-urlencoded"));
client.DefaultRequestHeaders.Add("Accept", "*/*");
var parameters = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("response", responseText),
new KeyValuePair<string, string>("secret", AppSettingsManager.hCaptchaSecretKey()),
new KeyValuePair<string, string>("remoteip", remoteIp)
};
var request = new HttpRequestMessage(HttpMethod.Post, "https://hcaptcha.com/siteverify")
{
Content = new FormUrlEncodedContent(parameters)
};
var response = client.SendAsync(request).Result;
if (response.IsSuccessStatusCode)
{
var jsonString = response.Content.ReadAsStringAsync();
jsonString.Wait();
var result = JsonConvert.DeserializeObject<hCaptchaVerifyResponse>(jsonString.Result);
if (result.Success)
{
return true;
}
}
if (!response.IsSuccessStatusCode)
{
return false;
}
}
return false;
}
}
using System;
using Newtonsoft.Json;
namespace UmbHost.Shared.Models.hCaptcha
{
/// <summary>
/// Response Model to get the verification result
/// </summary>
/// <remarks>https://docs.hcaptcha.com/#server</remarks>
public class hCaptchaVerifyResponse
{
/// <summary>
/// indicates if verify was successfully or not
/// </summary>
/// <remarks>https://docs.hcaptcha.com/#server</remarks>
[JsonProperty("success")]
public bool Success { get; set; }
/// <summary>
/// timestamp of the captcha (ISO format yyyy-MM-dd'T'HH:mm:ssZZ)
/// </summary>
/// <remarks>https://docs.hcaptcha.com/#server</remarks>
[JsonProperty("challenge_ts")]
public DateTimeOffset Timestamp { get; set; }
/// <summary>
/// the hostname of the site where the captcha was solved
/// </summary>
/// <remarks>https://docs.hcaptcha.com/#server</remarks>
[JsonProperty("hostname")]
public string Hostname { get; set; }
/// <summary>
/// optional: whether the response will be credited
/// </summary>
/// <remarks>https://docs.hcaptcha.com/#server</remarks>
[JsonProperty("credit")]
public bool Credit { get; set; }
/// <summary>
/// string based error code array
/// </summary>
/// <remarks>https://docs.hcaptcha.com/#server</remarks>
[JsonProperty("error-codes")]
public string[] ErrorCodes { get; set; }
}
}
public interface IhCaptchaService
{
bool Validate(string remoteIp, string responseText);
}
@using (Html.BeginUmbracoForm("FormPost", "AnySurface", null, new {autocomplete = "off"}, FormMethod.Post))
{
@Html.AntiForgeryToken()
<div class="h-captcha" data-sitekey="@AppSettingsManager.hCaptchaSiteKey()"></div>
}
<script src="https://hcaptcha.com/1/api.js"></script>
Add the below app settings:
<add key="hCaptchaSiteKey" value="" />
<add key="hCaptchaSecretKey" value="" />
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment