New Google Recaptcha with ASP.Net

I am trying to get the new Google reCaptcha working in my ASP.NET project and I am having problems with its new "I'm not a robot."

I had an old one there, and after a lot of research on developers.google.com everything looks the same (they even point me to downloading the same library - 1.0.5). So, I got new keys and entered them, and it works, but it looks just like the old reCaptcha.

Has anyone got a new one to work with their ASP.Net? What am I missing?

EDIT:

So, playing in a test application and browsing some other websites, I found that if I create such a page:

<html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <title>reCAPTCHA demo: Simple page</title> <script src="https://www.google.com/recaptcha/api.js" async defer></script> </head> <body> <form id="form1" runat="server" action="?" method="POST"> <div> <div class="g-recaptcha" data-sitekey="My Public Key"></div> <br/> <asp:Button ID="Button1" runat="server" Text="Submit" /> </div> </form> </body> </html> 

And then in my code-behind (Button1_Click), I do this:

 Dim Success As Boolean Dim recaptchaResponse As String = request.Form("g-recaptcha-response") If Not String.IsNullOrEmpty(recaptchaResponse) Then Success = True Else Success = False End If 

recaptchaResponse will be either empty or populated depending on whether they are a bot or not. The problem is that now I need to accept this answer and send it to Google using my private key so that I can make sure that the answer was not provided by the bot in my code, but I cannot figure out how to do it. I tried this (instead of Success = True ):

 Dim client As New System.Net.Http.HttpClient() client.BaseAddress = New Uri("https://www.google.com/recaptcha/") client.DefaultRequestHeaders.Accept.Clear() client.DefaultRequestHeaders.Accept.Add(New Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json")) Dim response As Net.Http.HttpResponseMessage = Await client.GetAsync("api/siteverify?secret=My Private key&response=" + recaptchaResponse) If (response.IsSuccessStatusCode) Then Dim CaptchResponse As ReCaptchaModel = Await response.Content.ReadAsAsync(Of ReCaptchaModel)() Success = CaptchResponse.success Else Success = False End If 

But I couldn’t figure out how to work with the asynchronous file, and I can’t find anything in that of ReCaptchaModel , so I found another way to call the web service and get the json response and tried this instead:

 Dim request As Net.WebRequest = Net.WebRequest.Create("https://www.google.com/recaptcha/") Dim Data As String = "api/siteverify?secret=My Private Key&response=" + recaptchaResponse request.Method = "POST" request.ContentType = "application/json; charset=utf-8" Dim postData As String = "{""data"":""" + Data + """}" 'get a reference to the request-stream, and write the postData to it Using s As IO.Stream = request.GetRequestStream() Using sw As New IO.StreamWriter(s) sw.Write(postData) End Using End Using 'get response-stream, and use a streamReader to read the content Using s As IO.Stream = request.GetResponse().GetResponseStream() Using sr As New IO.StreamReader(s) 'decode jsonData with javascript serializer Dim jsonData = sr.ReadToEnd() Stop End Using End Using 

But that just gives me the content of the webpage at https://www.google.com/recaptcha . Not what I want. The Google page is not very useful, and I am fixated on where to go. I need help calling a Google validation service, or if someone found another way to do this from ASP.NET.

+5
source share
4 answers

I just gave up when I came across something unrelated, which made me think about it again and differently. In my last attempt, I tried to pass the secret key and the recaptcha response as data, so I tried it in create WebRequest and it worked. Here is the final solution:

Using the same HTML as above, I created a function that I can call in the button click event, where I check Page.IsValid and call this function:

 Private Function IsGoogleCaptchaValid() As Boolean Try Dim recaptchaResponse As String = Request.Form("g-recaptcha-response") If Not String.IsNullOrEmpty(recaptchaResponse) Then Dim request As Net.WebRequest = Net.WebRequest.Create("https://www.google.com/recaptcha/api/siteverify?secret=My Private Key&response=" + recaptchaResponse) request.Method = "POST" request.ContentType = "application/json; charset=utf-8" Dim postData As String = "" 'get a reference to the request-stream, and write the postData to it Using s As IO.Stream = request.GetRequestStream() Using sw As New IO.StreamWriter(s) sw.Write(postData) End Using End Using ''get response-stream, and use a streamReader to read the content Using s As IO.Stream = request.GetResponse().GetResponseStream() Using sr As New IO.StreamReader(s) 'decode jsonData with javascript serializer Dim jsonData = sr.ReadToEnd() If jsonData = "{" & vbLf & " ""success"": true" & vbLf & "}" Then Return True End If End Using End Using End If Catch ex As Exception 'Dont show the error End Try Return False End Function 

I am sure there are improvements in the code, but it works. I could not see adding links to some JSON libraries to read one thing that I was just checking.

+7
source

Thanks for sharing this. It worked for me. I went ahead and converted it to C # (since then that I used) and added a few things.

  • I changed the check step. I split the JSON string and evaluated if success was found, where it should be.
  • I used ConfigurationManager to store ReCaptcha keys.
  • Finally, I replaced it with WebRequest and HttpClient . This cuts the code in half, because now I do not need to read the stream.

Feel free to use this code.

 private static bool IsReCaptchaValid(string response) { if (string.IsNullOrWhiteSpace(response)) { return false; } var client = new HttpClient(); string result = client.GetStringAsync(string.Format("{0}?secret={1}&response={2}", ConfigurationManager.AppSettings["ReCaptchaValidationLink"], ConfigurationManager.AppSettings["ReCaptchaSecretKey"], response)).Result; string[] split = result.Split('\"'); return split[1] == "success"; } 
0
source

I used a slightly different approach, using the data-callback parameter and the Session parameter. The following elements are inside the MainContent block of the MainContent file:

 <asp:ScriptManager ID="scrEnablePage" EnablePageMethods="true" runat="server" /> <asp:Panel ID="pnlCaptcha" runat="server" Visible="true"> <div class="g-recaptcha" data-sitekey='<asp:Literal ID="litKey" runat="server" Text="<%$ AppSettings:recaptchaPublicKey%>" />' data-callback="handleCaptcha"></div> </asp:Panel> <script src="https://www.google.com/recaptcha/api.js" async defer></script> <script type="text/javascript"> function handleCaptcha(e) { PageMethods.RecaptchaValid(e); location.reload(true); } </script> 

Then in the code:

 Private Const GoogleUrl As String = "https://www.google.com/recaptcha/api/siteverify?secret={0}&response={1}" Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load pnlCaptcha.Visible = Not (Session("VerifiedHuman") = "True") ... End Sub <System.Web.Services.WebMethod(EnableSession:=True)> _ Public Shared Sub RecaptchaValid(response As String) Dim client As New System.Net.WebClient() Dim outcome As Dictionary(Of String, String) Dim result As String = String.Join(vbCrLf, {"{", """success"": true", "}"}) Dim serializer As New System.Web.Script.Serialization.JavaScriptSerializer() Dim url As String = String.Format(GoogleUrl, ConfigurationManager.AppSettings.Get("recaptchaPrivateKey"), response) Try result = client.DownloadString(url) Catch ex As System.Net.WebException Exit Sub ' Comment out to default to passing End Try outcome = serializer.Deserialize(Of Dictionary(Of String, String))(result) HttpContext.Current.Session("VerifiedHuman") = outcome("success") End Sub 

Now in Page_Load you can check Session("VerifiedHuman") = "True" and update the page controls accordingly, hide the panel using the Captcha element and show other relevant elements.

Note that this takes the keys to Web.config , i.e.

 <configuration> <appSettings> <add key="recaptchaPublicKey" value="..." /> <add key="recaptchaPrivateKey" value="..." /> ... </appSettings> ... </configuration> 
0
source

This adds a few things. It converts the response from Google to a Json object, it adds a timeout for the validation request and adds hostname validation (Google requires this when sending requests from multiple domains, and the domains are not listed in the Google admin area).

 Imports Newtonsoft.Json Public Class Google Public Class ReCaptcha Private Const secret_key = "YOUR_SECRET_KEY" Public Shared Function Validate(Request As HttpRequest, hostname As String) As Boolean Dim g_captcha_response = Request.Form("g-recaptcha-response") If Not String.IsNullOrEmpty(g_captcha_response) Then Dim response = ExecuteVerification(g_captcha_response) If Not response.StartsWith("ERROR:") Then Dim json_obj = JsonConvert.DeserializeObject(Of ValidateResponse)(response) If json_obj.success Then If json_obj.hostname.ToLower = hostname.ToLower Then Return True End If End If End If Return False End Function Private Shared Function ExecuteVerification(g_captcha_response As String) As String Dim request As Net.WebRequest = Net.WebRequest.Create("https://www.google.com/recaptcha/api/siteverify?secret=" & secret_key & "&response=" & g_captcha_response) request.Timeout = 5 * 1000 ' 5 Seconds to avoid getting locked up request.Method = "POST" request.ContentType = "application/json" Try Dim byteArray As Byte() = Encoding.UTF8.GetBytes("") request.ContentLength = byteArray.Length Dim dataStream As Stream = request.GetRequestStream() dataStream.Write(byteArray, 0, byteArray.Length) dataStream.Close() Dim response As Net.WebResponse = request.GetResponse() dataStream = response.GetResponseStream() Dim reader As New StreamReader(dataStream) Dim responseFromServer As String = reader.ReadToEnd() reader.Close() response.Close() Return responseFromServer Catch ex As Exception Return "ERROR: " & ex.Message End Try End Function Public Class ValidateResponse Public Property success As Boolean Public Property challenge_ts As DateTime Public Property hostname As String <JsonProperty("error-codes")> Public Property error_codes As List(Of String) End Class End Class End Class 

So, on the Click event button, just call:

 If Google.ReCaptcha.Validate(Request, Request.Url.Host) Then ' good to go Else ' validation failed End If 
0
source

Source: https://habr.com/ru/post/1209288/


All Articles