Checking Recaptcha 2 (not CAPTCHA reCAPTCHA) on the ASP.NET server side

The new Recaptcha 2 looks promising, but I have not found a way to test it on the ASP.NET server side,

if(Page.IsValid) in This answer is valid for the old Recaptcha, but not the new one,

How to check new server side reCAPTCHA?

+64
c # recaptcha
Jan 04
source share
11 answers

After reading a lot of resources, I wrote this class to verify the correctness of the new ReCaptcha :

As mentioned here : When reCAPTCHA is decided by the end user, a new field (g-recaptcha-response) will be populated in HTML.

We need to read this value and pass it to the class below to check it:

In C #:

In the code behind your page:

 string EncodedResponse = Request.Form["g-Recaptcha-Response"]; bool IsCaptchaValid = (ReCaptchaClass.Validate(EncodedResponse) == "true" ? true : false); if (IsCaptchaValid) { //Valid Request } 

Grade:

  using Newtonsoft.Json; public class ReCaptchaClass { public static string Validate(string EncodedResponse) { var client = new System.Net.WebClient(); string PrivateKey = "6LcH-v8SerfgAPlLLffghrITSL9xM7XLrz8aeory"; var GoogleReply = client.DownloadString(string.Format("https://www.google.com/recaptcha/api/siteverify?secret={0}&response={1}", PrivateKey, EncodedResponse)); var captchaResponse = Newtonsoft.Json.JsonConvert.DeserializeObject<ReCaptchaClass>(GoogleReply); return captchaResponse.Success.ToLower(); } [JsonProperty("success")] public string Success { get { return m_Success; } set { m_Success = value; } } private string m_Success; [JsonProperty("error-codes")] public List<string> ErrorCodes { get { return m_ErrorCodes; } set { m_ErrorCodes = value; } } private List<string> m_ErrorCodes; } 

In VB.NET:

In the code behind your page:

 Dim EncodedResponse As String = Request.Form("g-Recaptcha-Response") Dim IsCaptchaValid As Boolean = IIf(ReCaptchaClass.Validate(EncodedResponse) = "True", True, False) If IsCaptchaValid Then 'Valid Request End If 

Grade:

 Imports Newtonsoft.Json Public Class ReCaptchaClass Public Shared Function Validate(ByVal EncodedResponse As String) As String Dim client = New System.Net.WebClient() Dim PrivateKey As String = "6dsfH-v8SerfgAPlLLffghrITSL9xM7XLrz8aeory" Dim GoogleReply = client.DownloadString(String.Format("https://www.google.com/recaptcha/api/siteverify?secret={0}&response={1}", PrivateKey, EncodedResponse)) Dim captchaResponse = Newtonsoft.Json.JsonConvert.DeserializeObject(Of ReCaptchaClass)(GoogleReply) Return captchaResponse.Success End Function <JsonProperty("success")> _ Public Property Success() As String Get Return m_Success End Get Set(value As String) m_Success = value End Set End Property Private m_Success As String <JsonProperty("error-codes")> _ Public Property ErrorCodes() As List(Of String) Get Return m_ErrorCodes End Get Set(value As List(Of String)) m_ErrorCodes = value End Set End Property Private m_ErrorCodes As List(Of String) End Class 
+140
Jan 04 '15 at 15:45
source share

The version of JavaScriptSerializer is used here. Thanks to Ala for the basis for this code.

Setting up a WebConfig application - I added a secret key to Web.Config in my case to allow conversions between environments. If necessary, it can also be easily encrypted.

 <add key="Google.ReCaptcha.Secret" value="123456789012345678901234567890" /> 

Class ReCaptcha . A simple class to send a response parameter along with your secret to Google and validate it. The response is deserialized using the .NET JavaScriptSerializer class and from the return value of true or false.

 using System.Collections.Generic; using System.Configuration; public class ReCaptcha { public bool Success { get; set; } public List<string> ErrorCodes { get; set; } public static bool Validate(string encodedResponse) { if (string.IsNullOrEmpty(encodedResponse)) return false; var client = new System.Net.WebClient(); var secret = ConfigurationManager.AppSettings["Google.ReCaptcha.Secret"]; if (string.IsNullOrEmpty(secret)) return false; var googleReply = client.DownloadString(string.Format("https://www.google.com/recaptcha/api/siteverify?secret={0}&response={1}", secret, encodedResponse)); var serializer = new System.Web.Script.Serialization.JavaScriptSerializer(); var reCaptcha = serializer.Deserialize<ReCaptcha>(googleReply); return reCaptcha.Success; } } 

Confirm the answer . Verify that the g-Recaptcha-Response form parameter in your controller (or code for the web form) is correct and follow the appropriate steps.

 var encodedResponse = Request.Form["g-Recaptcha-Response"]; var isCaptchaValid = ReCaptcha.Validate(encodedResponse); if (!isCaptchaValid) { // Eg Return to view or set an error message to visible } 
+42
Dec 04 '15 at 0:59
source share

Most of these answers seem more complicated than necessary. They also do not provide an IP address that will help prevent an interception attack ( https://security.stackexchange.com/questions/81865/is-there-any-reason-to-include-the-remote-ip-when-using - re-view ). That's where I left off

 public bool CheckCaptcha(string captchaResponse, string ipAddress) { using (var client = new WebClient()) { var response = client.DownloadString($"https://www.google.com/recaptcha/api/siteverify?secret={ ConfigurationManager.AppSettings["Google.ReCaptcha.Secret"] }&response={ captchaResponse }&remoteIp={ ipAddress }"); return (bool)JObject.Parse(response)["success"]; } } 
+14
Feb 23 '16 at 0:33
source share

You can use the "IsValidCaptcha ()" method to test server side Google Recaptcha. Replace your secret key with "YourRecaptchaSecretkey" in the following way.

 Public bool IsValidCaptcha() { string resp = Request["g-recaptcha-response"]; var req = (HttpWebRequest)WebRequest.Create (https://www.google.com/recaptcha/api/siteverify?secret=+ YourRecaptchaSecretkey + "&response=" + resp); using (WebResponse wResponse = req.GetResponse()) { using (StreamReader readStream = new StreamReader(wResponse.GetResponseStream())) { string jsonResponse = readStream.ReadToEnd(); JavaScriptSerializer js = new JavaScriptSerializer(); // Deserialize Json CaptchaResult data = js.Deserialize<CaptchaResult>(jsonResponse); if (Convert.ToBoolean(data.success)) { return true; } } } return false; } 

Also create the following class.

 public class CaptchaResult { public string success { get; set; } } 

Link link

+6
Aug 08 '16 at 11:30
source share

According to the doc, you simply post your private key and user response to the API and read the return property "success"

QUICK ANSWER:

  var webClient = new WebClient(); string verification = webClient.DownloadString(string.Format("https://www.google.com/recaptcha/api/siteverify?secret={0}&response={1}", secretKey, userResponse)); if (JObject.Parse(verification)["success"].Value<bool>()) { // SUCCESS!!! 

FULL EXAMPLE:

Suppose you put this page in IamNotARobotLogin.cshtml .

 <head> <script src="https://www.google.com/recaptcha/api.js" async defer></script> </head> <body> <form action="Login" method="POST"> <div class="g-recaptcha" data-sitekey="your_site_key"></div><br/> <input type="submit" value="Log In"> </form> </body> 

And suppose you want the controller to save, say, the flag "I_AM_NOT_ROBOT" in the session, if the check was successful:

  public ActionResult IamNotARobotLogin() { return View(); } [HttpPost] public ActionResult Login() { const string secretKey = "6LcH-v8SerfgAPlLLffghrITSL9xM7XLrz8aeory"; string userResponse = Request.Form["g-Recaptcha-Response"]; var webClient = new System.Net.WebClient(); string verification = webClient.DownloadString(string.Format("https://www.google.com/recaptcha/api/siteverify?secret={0}&response={1}", secretKey, userResponse)); var verificationJson = Newtonsoft.Json.Linq.JObject.Parse(verification); if (verificationJson["success"].Value<bool>()) { Session["I_AM_NOT_A_ROBOT"] = "true"; return RedirectToAction("Index", "Demo"); } // try again: return RedirectToAction("IamNotARobotLogin"); } 
+3
Dec 03 '16 at 21:23
source share

Here is my Ala solution plug for:

  • send parameter to POST
  • for disinfecting the input form
  • include requester IP address
  • Keep a secret in Web.Config:

In the controller:

 bool isCaptchaValid = await ReCaptchaClass.Validate(this.Request); if (!isCaptchaValid) { ModelState.AddModelError("", "Invalid captcha"); return View(model); } 

Utility Class:

 public class ReCaptchaClass { private static ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); private static string SecretKey = System.Configuration.ConfigurationManager.AppSettings["Google.ReCaptcha.Secret"]; [JsonProperty("success")] public bool Success { get; set; } [JsonProperty("error-codes")] public List<string> ErrorCodes { get; set; } public static async Task<bool> Validate(HttpRequestBase Request) { string encodedResponse = Request.Form["g-Recaptcha-Response"]; string remoteIp = Request.UserHostAddress; using (var client = new HttpClient()) { var values = new Dictionary<string, string> { {"secret", SecretKey}, {"remoteIp", remoteIp}, {"response", encodedResponse} }; var content = new FormUrlEncodedContent(values); var response = await client.PostAsync("https://www.google.com/recaptcha/api/siteverify", content); var responseString = await response.Content.ReadAsStringAsync(); var captchaResponse = Newtonsoft.Json.JsonConvert.DeserializeObject<ReCaptchaClass>(responseString); if ((captchaResponse.ErrorCodes?.Count ?? 0) != 0) { log.Warn("ReCaptcha errors: " + string.Join("\n", captchaResponse.ErrorCodes)); } return captchaResponse.Success; } } } 
+3
Dec 14 '16 at 12:59
source share

Another example is posted here:

RecaptchaV2.NET (Github)

It also implements the Recaptcha 2.0 safe marker option (look at the full source code for this bit, I deleted the corresponding code fragments ONLY to verify the result).

It does not depend on the parser newtonsoft json and instead uses the built-in .NET.

Here is the corresponding code snippet from the RecaptchaV2.NET library (from recaptcha.cs):

 namespace RecaptchaV2.NET { /// <summary> /// Helper Methods for the Google Recaptcha V2 Library /// </summary> public class Recaptcha { public string SiteKey { get; set; } public string SecretKey { get; set; } public Guid SessionId { get; set; } /// <summary> /// Validates a Recaptcha V2 response. /// </summary> /// <param name="recaptchaResponse">g-recaptcha-response form response variable (HttpContext.Current.Request.Form["g-recaptcha-response"])</param> /// <returns>RecaptchaValidationResult</returns> public RecaptchaValidationResult Validate(string recaptchaResponse) { RecaptchaValidationResult result = new RecaptchaValidationResult(); HttpWebRequest req = (HttpWebRequest)WebRequest.Create("https://www.google.com/recaptcha/api/siteverify?secret=" + SecretKey + "&response=" + recaptchaResponse + "&remoteip=" + GetClientIp()); //Google recaptcha Response using (WebResponse wResponse = req.GetResponse()) { using (StreamReader readStream = new StreamReader(wResponse.GetResponseStream())) { string jsonResponse = readStream.ReadToEnd(); JavaScriptSerializer js = new JavaScriptSerializer(); result = js.Deserialize<RecaptchaValidationResult>(jsonResponse.Replace("error-codes", "ErrorMessages").Replace("success", "Succeeded"));// Deserialize Json } } return result; } private string GetClientIp() { // Look for a proxy address first String _ip = HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"]; // If there is no proxy, get the standard remote address if (string.IsNullOrWhiteSpace(_ip) || _ip.ToLower() == "unknown") _ip = HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"]; return _ip; } } public class RecaptchaValidationResult { public RecaptchaValidationResult() { ErrorMessages = new List<string>(); Succeeded = false; } public List<string> ErrorMessages { get; set; } public bool Succeeded { get; set; } public string GetErrorMessagesString() { return string.Join("<br/>", ErrorMessages.ToArray()); } } } 
+1
Aug 05 '15 at 17:04
source share

The Google ReCaptcha API no longer accepts the payload as query string parameters in a GET request. Google always returned a β€œfalse” success response if I did not send the data via HTTP POST. Here is an update to the Ala class (excellent!) That sends the payload to the endpoint of the Google service:

 using Newtonsoft.Json; using System.Net; using System.IO; using System.Text; public class RecaptchaHandler { public static string Validate(string EncodedResponse, string RemoteIP) { var client = new WebClient(); string PrivateKey = "PRIVATE KEY"; WebRequest req = WebRequest.Create("https://www.google.com/recaptcha/api/siteverify"); string postData = String.Format("secret={0}&response={1}&remoteip={2}", PrivateKey, EncodedResponse, RemoteIP); byte[] send = Encoding.Default.GetBytes(postData); req.Method = "POST"; req.ContentType = "application/x-www-form-urlencoded"; req.ContentLength = send.Length; Stream sout = req.GetRequestStream(); sout.Write(send, 0, send.Length); sout.Flush(); sout.Close(); WebResponse res = req.GetResponse(); StreamReader sr = new StreamReader(res.GetResponseStream()); string returnvalue = sr.ReadToEnd(); var captchaResponse = JsonConvert.DeserializeObject<RecaptchaHandler>(returnvalue); return captchaResponse.Success; } [JsonProperty("success")] public string Success { get { return m_Success; } set { m_Success = value; } } private string m_Success; [JsonProperty("error-codes")] public List<string> ErrorCodes { get { return m_ErrorCodes; } set { m_ErrorCodes = value; } } private List<string> m_ErrorCodes; } 
+1
Sep 28 '16 at 21:16
source share

Using dynamic to check server side recaptcha

Call function

 [HttpPost] public ActionResult ClientOrderDetail(FormCollection collection, string EncodedResponse) { Boolean Validation = myFunction.ValidateRecaptcha(EncodedResponse); return View(); } 

Function Declaration

 public static Boolean ValidateRecaptcha(string EncodedResponse) { string PrivateKey = "YourSiteKey"; var client = new System.Net.WebClient(); var GoogleReply = client.DownloadString(string.Format("https://www.google.com/recaptcha/api/siteverify?secret={0}&response={1}", PrivateKey, EncodedResponse)); var serializer = new JavaScriptSerializer(); dynamic data = serializer.Deserialize(GoogleReply, typeof(object)); Boolean Status = data["success"]; string challenge_ts = data["challenge_ts"]; string hostname = data["hostname"]; return Status; } 
0
Sep 01 '16 at 11:47
source share

in the example I posted in so post uses Newtonsoft.JSON to deserialize the full returned JSON, puts the data in Google (as opposed to using querystring) stores the corresponding variables in the web.config file, rather than hardcoded ones.

0
Jan 15 '17 at 18:49
source share

This article provides a clear step-by-step explanation of how to implement the ReCaptcha validation attribute in your model.

First create a Recaptcha validation attribute.

 namespace Sample.Validation { public class GoogleReCaptchaValidationAttribute : ValidationAttribute { protected override ValidationResult IsValid(object value, ValidationContext validationContext) { Lazy<ValidationResult> errorResult = new Lazy<ValidationResult>(() => new ValidationResult("Google reCAPTCHA validation failed", new String[] { validationContext.MemberName })); if (value == null || String.IsNullOrWhiteSpace( value.ToString())) { return errorResult.Value; } IConfiguration configuration = (IConfiguration)validationContext.GetService(typeof(IConfiguration)); String reCaptchResponse = value.ToString(); String reCaptchaSecret = configuration.GetValue<String>("GoogleReCaptcha:SecretKey"); HttpClient httpClient = new HttpClient(); var httpResponse = httpClient.GetAsync($"https://www.google.com/recaptcha/api/siteverify?secret={reCaptchaSecret}&response={reCaptchResponse}").Result; if (httpResponse.StatusCode != HttpStatusCode.OK) { return errorResult.Value; } String jsonResponse = httpResponse.Content.ReadAsStringAsync().Result; dynamic jsonData = JObject.Parse(jsonResponse); if (jsonData.success != true.ToString().ToLower()) { return errorResult.Value; } return ValidationResult.Success; } } } 

Then add the validation attribute to your model.

 namespace Sample.Models { public class XModel { // ... [Required] [GoogleReCaptchaValidation] public String GoogleReCaptchaResponse { get; set; } } } 

Finally, you just need to call the ModelState.IsValid method

 namespace Sample.Api.Controllers { [ApiController] public class XController : ControllerBase { [HttpPost] public IActionResult Post(XModel model) { if (!ModelState.IsValid) { return BadRequest(ModelState); } // ... } } } 

Et voila! :)

0
Jul 21 '19 at 12:32
source share



All Articles