· 7 years ago · Sep 07, 2018, 10:06 AM
1
2Log In Sign Up
3This site uses cookies to deliver our services and to show you relevant ads and job listings. By using our site, you acknowledge that you have read and understand our Cookie Policy, Privacy Policy, and our Terms of Service. Your use of Stack Overflow’s Products and Services, including the Stack Overflow Network, is subject to these policies and terms.
4
5Join Stack Overflow to learn, share knowledge, and build your career.
6
7Email Sign Up
8OR SIGN IN WITH
9 Google
10 Facebook
11Home
12PUBLIC
13Stack Overflow
14Tags
15Users
16Jobs
17Teams
18Q&A for work
19Learn More
20Validating Recaptcha 2 (No CAPTCHA reCAPTCHA) in ASP.NET's server side
21Ask Question
22up vote
2355
24down vote
25favorite
2622
27The new Recaptcha 2 looks promising, but i didn't find a way to validate it in ASP.NET's server side,
28
29if(Page.IsValid) in This answer, is valid for the old Recaptcha, but not the new one,
30
31How to validate the new reCAPTCHA in server side?
32
33c# asp.net vb.net recaptcha
34shareimprove this question
35edited May 23 '17 at 10:31
36
37Community♦
3811
39asked Jan 4 '15 at 10:43
40
41Alaa
424,614144277
43Don't they have rest endpoints to validate – Saravanan Jan 4 '15 at 10:56
44Try this. You have to post user response to google ans based on response, proceed. More here. developers.google.com/recaptcha/docs/verify – Saravanan Jan 4 '15 at 11:00
45@saravanan, You're right, the solution should be here, i will try to code it. – Alaa Jan 4 '15 at 11:06
461
47Try this Install-Package reCAPTCH.MVC – Sender Aug 7 '15 at 3:53
48add a comment
4910 Answers
50active oldest votes
51up vote
52118
53down vote
54accepted
55After reading many resources, I ended up with writing this class to handle the validation of the new ReCaptcha :
56
57As mentioned Here : When a reCAPTCHA is solved by end user, a new field (g-recaptcha-response) will be populated in HTML.
58
59We need to read this value and pass it to the class below to validate it:
60
61In C#:
62
63In the code behind of your page :
64
65string EncodedResponse = Request.Form["g-Recaptcha-Response"];
66bool IsCaptchaValid = (ReCaptchaClass.Validate(EncodedResponse) == "true" ? true : false);
67
68if (IsCaptchaValid) {
69 //Valid Request
70}
71The Class:
72
73 using Newtonsoft.Json;
74
75 public class ReCaptchaClass
76 {
77 public static string Validate(string EncodedResponse)
78 {
79 var client = new System.Net.WebClient();
80
81 string PrivateKey = "6LcH-v8SerfgAPlLLffghrITSL9xM7XLrz8aeory";
82
83 var GoogleReply = client.DownloadString(string.Format("https://www.google.com/recaptcha/api/siteverify?secret={0}&response={1}", PrivateKey, EncodedResponse));
84
85 var captchaResponse = Newtonsoft.Json.JsonConvert.DeserializeObject<ReCaptchaClass>(GoogleReply);
86
87 return captchaResponse.Success.ToLower();
88 }
89
90 [JsonProperty("success")]
91 public string Success
92 {
93 get { return m_Success; }
94 set { m_Success = value; }
95 }
96
97 private string m_Success;
98 [JsonProperty("error-codes")]
99 public List<string> ErrorCodes
100 {
101 get { return m_ErrorCodes; }
102 set { m_ErrorCodes = value; }
103 }
104
105
106 private List<string> m_ErrorCodes;
107 }
108In VB.NET:
109
110In the code behind of your page :
111
112Dim EncodedResponse As String = Request.Form("g-Recaptcha-Response")
113 Dim IsCaptchaValid As Boolean = IIf(ReCaptchaClass.Validate(EncodedResponse) = "True", True, False)
114
115 If IsCaptchaValid Then
116 'Valid Request
117 End If
118The Class:
119
120Imports Newtonsoft.Json
121
122
123Public Class ReCaptchaClass
124 Public Shared Function Validate(ByVal EncodedResponse As String) As String
125 Dim client = New System.Net.WebClient()
126
127 Dim PrivateKey As String = "6dsfH-v8SerfgAPlLLffghrITSL9xM7XLrz8aeory"
128
129 Dim GoogleReply = client.DownloadString(String.Format("https://www.google.com/recaptcha/api/siteverify?secret={0}&response={1}", PrivateKey, EncodedResponse))
130
131 Dim captchaResponse = Newtonsoft.Json.JsonConvert.DeserializeObject(Of ReCaptchaClass)(GoogleReply)
132
133 Return captchaResponse.Success
134 End Function
135
136 <JsonProperty("success")> _
137 Public Property Success() As String
138 Get
139 Return m_Success
140 End Get
141 Set(value As String)
142 m_Success = value
143 End Set
144 End Property
145 Private m_Success As String
146
147 <JsonProperty("error-codes")> _
148 Public Property ErrorCodes() As List(Of String)
149 Get
150 Return m_ErrorCodes
151 End Get
152 Set(value As List(Of String))
153 m_ErrorCodes = value
154 End Set
155 End Property
156
157 Private m_ErrorCodes As List(Of String)
158
159End Class
160shareimprove this answer
161edited May 15 at 0:50
162
163Donnelle
1644,91632030
165answered Jan 4 '15 at 15:45
166
167Alaa
1684,614144277
1697
170And if users don't want to import Newtonsoft.Json and create a whole defined Json object, they could just use JavaScriptSerializer from System.Web.Script.Serialization and deserialise to a plain 'ol object, like shown in this stackexchange answer – monty Mar 2 '15 at 3:04
1714
172Your answer was really helpful Ala. This is what I did to remove the dependency on Newtonsoft: JavaScriptSerializer js = new JavaScriptSerializer(); MyObject data = js.Deserialize<MyObject>(GoogleReply); var captchaResponse = data.success; return captchaResponse.ToString(); } public class MyObject { public string success { get; set; } } – smoore4 Mar 3 '15 at 19:10
1732
174Thank you Ala. A side note, in the code, bool IsCaptchaValid = (ReCaptchaClass.Validate(EncodedResponse) == "True" ? true : false);, you don't need the ? true : false, it's redundant. – Bryan Mar 18 '15 at 17:18
1751
176btw I would not share private key here. Make a new one for your app – stenly Apr 6 '16 at 0:01
1772
178Just to say, the result from the Validate function is true with small t and hence I was pulling my hair out why it was not working. – cocojiambo Mar 14 '17 at 21:30
179show 4 more comments
180up vote
18138
182down vote
183Here's a version that uses the JavaScriptSerializer. Thanks Ala for the basis for this code.
184
185WebConfig App Setting - I've added the secret key to the Web.Config in my case to allow transforms between environments. It can also be easily encrypted here if required.
186
187<add key="Google.ReCaptcha.Secret" value="123456789012345678901234567890" />
188The ReCaptcha Class - A simple class to post the response parameter along with your secret to Google and validate it. The response is deserialized using the .Net JavaScriptSerializer class and from that true or false returned.
189
190using System.Collections.Generic;
191using System.Configuration;
192
193public class ReCaptcha
194{
195 public bool Success { get; set; }
196 public List<string> ErrorCodes { get; set; }
197
198 public static bool Validate(string encodedResponse)
199 {
200 if (string.IsNullOrEmpty(encodedResponse)) return false;
201
202 var client = new System.Net.WebClient();
203 var secret = ConfigurationManager.AppSettings["Google.ReCaptcha.Secret"];
204
205 if (string.IsNullOrEmpty(secret)) return false;
206
207 var googleReply = client.DownloadString(string.Format("https://www.google.com/recaptcha/api/siteverify?secret={0}&response={1}", secret, encodedResponse));
208
209 var serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
210
211 var reCaptcha = serializer.Deserialize<ReCaptcha>(googleReply);
212
213 return reCaptcha.Success;
214 }
215}
216Validate The Response - Check the validity of the g-Recaptcha-Response form parameter in your Controller (or code behind for a web form) and take appropriate action.
217
218var encodedResponse = Request.Form["g-Recaptcha-Response"];
219var isCaptchaValid = ReCaptcha.Validate(encodedResponse);
220
221if (!isCaptchaValid)
222{
223 // E.g. Return to view or set an error message to visible
224}
225shareimprove this answer
226edited Dec 4 '15 at 1:44
227answered Dec 4 '15 at 0:59
228
229Paul
23052945
2313
232This seems to be a good solution for those interested in the simplest implementation, especially without using the Newtonsoft libraries. – Mark Dec 29 '15 at 16:39
2332
234I went with this solution. Simple, good explanation, and easy to follow. – Scribblemacher Mar 22 '16 at 17:00
235this does not work if already a client-side validation, cause the response is successful only once, not twice, so if already validated by the client side, the server second validation will return false... – Serge Apr 23 at 9:36
236add a comment
237up vote
23811
239down vote
240Most of these answers seem more complex than needed. They also dont specify the IP which will help prevent a interception attack (https://security.stackexchange.com/questions/81865/is-there-any-reason-to-include-the-remote-ip-when-using-recaptcha). Here's what I settled on
241
242public bool CheckCaptcha(string captchaResponse, string ipAddress)
243{
244 using (var client = new WebClient())
245 {
246 var response = client.DownloadString($"https://www.google.com/recaptcha/api/siteverify?secret={ ConfigurationManager.AppSettings["Google.ReCaptcha.Secret"] }&response={ captchaResponse }&remoteIp={ ipAddress }");
247 return (bool)JObject.Parse(response)["success"];
248 }
249}
250shareimprove this answer
251edited May 8 at 0:52
252answered Feb 23 '16 at 0:33
253
254Luke McGregor
25522.6k1295146
256add a comment
257up vote
2586
259down vote
260You can use "IsValidCaptcha()" method to validate your google recaptcha on server side. Replace your secret key with "YourRecaptchaSecretkey" in the following method.
261
262Public bool IsValidCaptcha()
263 {
264 string resp = Request["g-recaptcha-response"];
265 var req = (HttpWebRequest)WebRequest.Create
266 (https://www.google.com/recaptcha/api/siteverify?secret=+ YourRecaptchaSecretkey + "&response=" + resp);
267 using (WebResponse wResponse = req.GetResponse())
268 {
269 using (StreamReader readStream = new StreamReader(wResponse.GetResponseStream()))
270 {
271 string jsonResponse = readStream.ReadToEnd();
272 JavaScriptSerializer js = new JavaScriptSerializer();
273 // Deserialize Json
274 CaptchaResult data = js.Deserialize<CaptchaResult>(jsonResponse);
275 if (Convert.ToBoolean(data.success))
276 {
277 return true;
278 }
279 }
280 }
281 return false;
282 }
283Also create following class as well.
284
285public class CaptchaResult
286 {
287 public string success { get; set; }
288 }
289Reference link
290
291shareimprove this answer
292edited Mar 6 '17 at 9:42
293answered Aug 8 '16 at 11:30
294
295Tabish Usman
2961,69321113
297thanks for sharing the code it works for me. – Sohail Ali Mar 13 '17 at 10:11
298add a comment
299up vote
3003
301down vote
302According to the doc you just post your secret key and user's answer to API and read returned "success" property
303
304SHORT ANSWER:
305
306 var webClient = new WebClient();
307 string verification = webClient.DownloadString(string.Format("https://www.google.com/recaptcha/api/siteverify?secret={0}&response={1}", secretKey, userResponse));
308 if (JObject.Parse(verification)["success"].Value<bool>())
309 {
310 // SUCCESS!!!
311FULL EXAMPLE:
312
313Suppose, you implement this page in IamNotARobotLogin.cshtml.
314
315<head>
316 <script src="https://www.google.com/recaptcha/api.js" async defer></script>
317</head>
318<body>
319<form action="Login" method="POST">
320 <div class="g-recaptcha" data-sitekey="your_site_key"></div><br/>
321 <input type="submit" value="Log In">
322</form>
323</body>
324And suppose you wish the controller saved, let's say, "I_AM_NOT_ROBOT" flag in the session if the verification succeeded:
325
326 public ActionResult IamNotARobotLogin()
327 {
328 return View();
329 }
330
331 [HttpPost]
332 public ActionResult Login()
333 {
334 const string secretKey = "6LcH-v8SerfgAPlLLffghrITSL9xM7XLrz8aeory";
335 string userResponse = Request.Form["g-Recaptcha-Response"];
336
337 var webClient = new System.Net.WebClient();
338 string verification = webClient.DownloadString(string.Format("https://www.google.com/recaptcha/api/siteverify?secret={0}&response={1}", secretKey, userResponse));
339
340 var verificationJson = Newtonsoft.Json.Linq.JObject.Parse(verification);
341 if (verificationJson["success"].Value<bool>())
342 {
343 Session["I_AM_NOT_A_ROBOT"] = "true";
344 return RedirectToAction("Index", "Demo");
345 }
346
347 // try again:
348 return RedirectToAction("IamNotARobotLogin");
349 }
350shareimprove this answer
351answered Dec 3 '16 at 21:23
352
353epox
354728712
355Nice one! worked like charm! – Gerrie Pretorius Jan 21 '17 at 11:38
356add a comment
357up vote
3582
359down vote
360Here's my fork of Ala's solution in order to:
361
362send paramter in POST
363to sanitize the form input
364include the requester IP address
365store the secret in Web.Config:
366In the controller:
367
368bool isCaptchaValid = await ReCaptchaClass.Validate(this.Request);
369if (!isCaptchaValid)
370{
371 ModelState.AddModelError("", "Invalid captcha");
372 return View(model);
373}
374The utility class:
375
376public class ReCaptchaClass
377{
378 private static ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
379 private static string SecretKey = System.Configuration.ConfigurationManager.AppSettings["Google.ReCaptcha.Secret"];
380 [JsonProperty("success")]
381 public bool Success { get; set; }
382 [JsonProperty("error-codes")]
383 public List<string> ErrorCodes { get; set; }
384
385 public static async Task<bool> Validate(HttpRequestBase Request)
386 {
387 string encodedResponse = Request.Form["g-Recaptcha-Response"];
388 string remoteIp = Request.UserHostAddress;
389 using (var client = new HttpClient())
390 {
391 var values = new Dictionary<string, string>
392 {
393 {"secret", SecretKey},
394 {"remoteIp", remoteIp},
395 {"response", encodedResponse}
396 };
397 var content = new FormUrlEncodedContent(values);
398 var response = await client.PostAsync("https://www.google.com/recaptcha/api/siteverify", content);
399 var responseString = await response.Content.ReadAsStringAsync();
400 var captchaResponse = Newtonsoft.Json.JsonConvert.DeserializeObject<ReCaptchaClass>(responseString);
401 if ((captchaResponse.ErrorCodes?.Count ?? 0) != 0)
402 {
403 log.Warn("ReCaptcha errors: " + string.Join("\n", captchaResponse.ErrorCodes));
404 }
405 return captchaResponse.Success;
406 }
407 }
408}
409shareimprove this answer
410answered Dec 14 '16 at 12:59
411
412Olivier de Rivoyre
4131,08511321
414add a comment
415up vote
4161
417down vote
418Another example is posted here:
419
420RecaptchaV2.NET (Github)
421
422It also implements the secure token option of Recaptcha 2.0 (look at full source code for that bit, I have stripped out relevant pieces of code ONLY for validating a result).
423
424This one doesn't rely on newtonsoft's json parser and instead uses the built in .NET one.
425
426Here is the relevant snippet of code from the RecaptchaV2.NET library (from recaptcha.cs):
427
428namespace RecaptchaV2.NET
429{
430 /// <summary>
431 /// Helper Methods for the Google Recaptcha V2 Library
432 /// </summary>
433 public class Recaptcha
434 {
435
436 public string SiteKey { get; set; }
437 public string SecretKey { get; set; }
438 public Guid SessionId { get; set; }
439
440 /// <summary>
441 /// Validates a Recaptcha V2 response.
442 /// </summary>
443 /// <param name="recaptchaResponse">g-recaptcha-response form response variable (HttpContext.Current.Request.Form["g-recaptcha-response"])</param>
444 /// <returns>RecaptchaValidationResult</returns>
445 public RecaptchaValidationResult Validate(string recaptchaResponse)
446 {
447 RecaptchaValidationResult result = new RecaptchaValidationResult();
448
449 HttpWebRequest req = (HttpWebRequest)WebRequest.Create("https://www.google.com/recaptcha/api/siteverify?secret=" + SecretKey + "&response="
450 + recaptchaResponse + "&remoteip=" + GetClientIp());
451 //Google recaptcha Response
452 using (WebResponse wResponse = req.GetResponse())
453 {
454 using (StreamReader readStream = new StreamReader(wResponse.GetResponseStream()))
455 {
456 string jsonResponse = readStream.ReadToEnd();
457
458 JavaScriptSerializer js = new JavaScriptSerializer();
459 result = js.Deserialize<RecaptchaValidationResult>(jsonResponse.Replace("error-codes", "ErrorMessages").Replace("success", "Succeeded"));// Deserialize Json
460 }
461 }
462
463 return result;
464 }
465
466 private string GetClientIp()
467 {
468 // Look for a proxy address first
469 String _ip = HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
470
471 // If there is no proxy, get the standard remote address
472 if (string.IsNullOrWhiteSpace(_ip) || _ip.ToLower() == "unknown")
473 _ip = HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
474
475 return _ip;
476 }
477 }
478
479 public class RecaptchaValidationResult
480 {
481 public RecaptchaValidationResult()
482 {
483 ErrorMessages = new List<string>();
484 Succeeded = false;
485 }
486
487 public List<string> ErrorMessages { get; set; }
488 public bool Succeeded { get; set; }
489
490 public string GetErrorMessagesString()
491 {
492 return string.Join("<br/>", ErrorMessages.ToArray());
493 }
494 }
495}