vb.net 使用 ASP.Net 的新 Google Recaptcha
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/27515838/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
New Google Recaptcha with ASP.Net
提问by Steve
I am attempting to get the new Google reCaptchaworking in my ASP.NET project and I am having problems getting it to be the new one "I'm not a robot".
我试图让新的Google reCaptcha在我的 ASP.NET 项目中工作,但我在让它成为新的“我不是机器人”时遇到了问题。
I had the old one in there and after doing much research on the developers.google.com web site, everything looks the same (they even point me to a download of the same dll - 1.0.5). So, I got the new keys and put them in and it works but it looks just like the old reCaptcha.
我在那里有旧的,在对 developer.google.com 网站做了大量研究之后,一切看起来都一样(他们甚至指向我下载相同的 dll - 1.0.5)。所以,我拿到了新钥匙并将它们放进去,它可以工作,但它看起来就像旧的 reCaptcha。
Has anyone gotten the new one to work with their ASP.Net? What am I missing?
有没有人让新的与他们的 ASP.Net 一起工作?我错过了什么?
EDIT:
编辑:
So playing around in a test app and searching some other web sites I found that if I create a page like this:
所以在测试应用程序中玩弄并搜索其他一些网站,我发现如果我创建一个这样的页面:
<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:
然后在我的代码隐藏(Button1_Click)中,我这样做:
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
The recaptchaResponsewill either be empty or filled in depending on if they are a bot or not. The issue is, I now need to take this response and send it to google with my private key so I can verify that the response was not provided by a bot, in my code-behind, but I cannot figure out how. I tried this (in place of Success = True):
该recaptchaResponse要么是空的或填充取决于他们是否是僵尸或没有。问题是,我现在需要接受此响应并将其与我的私钥一起发送给谷歌,以便我可以在我的代码隐藏中验证响应不是由机器人提供的,但我无法弄清楚如何。我试过这个(代替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 could not figure out how to get the async stuff working and I cannot find anything on what ReCaptchaModelis, so I found another way to call a web service and get a json response and tried this instead:
但是,我不知道如何让异步的东西工作,我找不到任何关于什么的东西ReCaptchaModel,所以我找到了另一种调用 Web 服务并获得 json 响应的方法,并尝试了这个:
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, this just gives me the content of the web page at https://www.google.com/recaptcha. Not what I want. The Google pageisn't very useful and I am stuck on where to go. I need some help either calling the Google verify service or if anyone has found another way to do this from ASP.NET.
但是,这只是给了我https://www.google.com/recaptcha网页的内容。不是我想要的。在谷歌网页是不是非常有用,我卡在哪里去了。我需要一些帮助来调用 Google 验证服务,或者是否有人找到了从 ASP.NET 执行此操作的另一种方法。
回答by Steve
I had just about given up when I ran across something unrelated that made me think about it again and in a different way. In my last attempt above, I was attempting to pass the private key and recaptcha response as the data, so I tried it in the createof the WebRequest and it worked. Here is the final solution:
当我遇到一些无关紧要的事情让我以不同的方式再次思考它时,我几乎要放弃了。在我上面的最后一次尝试中,我试图将私钥和 recaptcha 响应作为数据传递,所以我create在 WebRequest 中尝试了它并且它起作用了。这是最终的解决方案:
Using the same HTML posted above, I created a function that I can call in the button click event where I check the Page.IsValid and call this function:
使用上面发布的相同 HTML,我创建了一个函数,我可以在按钮单击事件中调用该函数,在那里我检查 Page.IsValid 并调用此函数:
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'm sure there are improvements to be made to the code, but it works. I couldn't see adding references to some JSON libraries for reading one thing I just check the string.
我确信代码有待改进,但它有效。我看不到添加对某些 JSON 库的引用以读取我只检查字符串的一件事。
回答by AVenger
Thank you for sharing this. It worked for me. I went ahead and converted it to C# (since that's what I was using) and added a few things.
感谢您分享这个。它对我有用。我继续将其转换为 C#(因为这是我使用的)并添加了一些内容。
- I changed the validation step. I split the JSON string and evaluated if success was found where it should be.
- I used the
ConfigurationManagerto store the ReCaptcha Keys. - Finally, I changed it from using a WebRequest to using and
HttpClient. This cut the code in half because I don't need to read the stream now.
- 我更改了验证步骤。我拆分了 JSON 字符串并评估是否在应有的位置找到了成功。
- 我用
ConfigurationManager来存储 ReCaptcha 密钥。 - 最后,我将其从使用 WebRequest 更改为使用 and
HttpClient。这将代码减半,因为我现在不需要读取流。
Feel free to use this code as well.
也可以随意使用此代码。
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";
}
回答by jonrsharpe
I took a slightly different approach, using the data-callbackoption and a Sessionparameter. The following sits within the MainContentblock of the .aspxfile:
我采用了稍微不同的方法,使用data-callback选项和Session参数。以下内容位于文件MainContent块中.aspx:
<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-behind:
然后在代码隐藏中:
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_Loadyou can check Session("VerifiedHuman") = "True"and update your page controls accordingly, hiding the panel with the Captcha control and showing the other appropriate items.
现在,Page_Load您可以相应地检查Session("VerifiedHuman") = "True"和更新页面控件,隐藏带有验证码控件的面板并显示其他适当的项目。
Note that this takes the keys from Web.config, i.e.
请注意,这从 中获取密钥Web.config,即
<configuration>
<appSettings>
<add key="recaptchaPublicKey" value="..." />
<add key="recaptchaPrivateKey" value="..." />
...
</appSettings>
...
</configuration>
回答by Shaun Peet
This adds a few things. It converts the response from Google into a Json object, it adds a timeout on the verification request, and it adds a verification of the hostname (required by Google if sending requests from multiple domains and the domains aren't listed in the Google Admin area).
这增加了一些东西。它将来自 Google 的响应转换为 Json 对象,在验证请求上添加超时,并添加对主机名的验证(如果从多个域发送请求并且域未在 Google 管理区域中列出,则需要由 Google 提供) )。
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 in the button's Click event, just call:
所以在按钮的 Click 事件中,只需调用:
If Google.ReCaptcha.Validate(Request, Request.Url.Host) Then
' good to go
Else
' validation failed
End If

