【问题标题】:New Google Recaptcha with ASP.Net使用 ASP.Net 的新 Google Recaptcha
【发布时间】:2014-12-16 23:27:45
【问题描述】:

我正在尝试让新的Google reCaptcha 在我的 ASP.NET 项目中工作,但我无法让它成为新的“我不是机器人”。

我在那里有旧的,在对 developers.google.com 网站进行了大量研究之后,一切看起来都一样(他们甚至指向我下载相同的 dll - 1.0.5)。所以,我得到了新密钥并将它们放入,它可以工作,但它看起来就像旧的 reCaptcha。

有没有人得到新的与他们的 ASP.Net 一起工作?我错过了什么?

编辑:

所以在一个测试应用中玩耍并搜索其他一些网站,我发现如果我创建一个这样的页面:

<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>

然后在我的代码隐藏 (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

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

但是,我不知道如何让异步的东西工作,我找不到任何关于 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

但是,这只是给了我https://www.google.com/recaptcha 的网页内容。不是我想要的。 Google page 不是很有用,我不知道该去哪里。我需要一些帮助,要么调用 Google 验证服务,要么如果有人从 ASP.NET 找到了另一种方法。

【问题讨论】:

  • 第二个答案对我有用。如果其中任何一个对您有用,那么您可能希望选择一个正确的,以便未来的人们可以知道要使用哪种解决方案。只是一个建议:)

标签: asp.net vb.net recaptcha


【解决方案1】:

当我遇到一些无关的事情让我以不同的方式重新思考它时,我正要放弃。在我上面的最后一次尝试中,我试图将私钥和 recaptcha 响应作为数据传递,所以我在 WebRequest 的create 中尝试了它并且它有效。这是最终的解决方案:

使用上面发布的相同 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

我确信对代码进行了改进,但它确实有效。我看不到添加对某些 JSON 库的引用来读取我只检查字符串的一件事。

【讨论】:

  • 顺便说一句,前几天服务返回的 JSON 略有变化,因此失败了。我建议以不同于上面说明的方式阅读 JSON。
  • 是的,JSON 变了,考虑使用 jsonData.Contains("""success"": true") 作为检查
【解决方案2】:

感谢您分享此内容。它对我有用。我继续将其转换为 C#(因为这是我使用的)并添加了一些东西。

  • 我更改了验证步骤。我拆分 JSON 字符串并评估是否在应有的位置找到了成功。
  • 我使用ConfigurationManager 来存储 ReCaptcha 密钥。
  • 最后,我将它从使用 WebRequest 更改为使用和HttpClient。这将代码减半,因为我现在不需要读取流。

您也可以随意使用此代码。

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";
}

【讨论】:

    【解决方案3】:

    我采用了一种稍微不同的方法,使用data-callback 选项和Session 参数。以下内容位于.aspx 文件的MainContent 块中:

    <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>
    

    然后在代码隐藏中:

    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
    

    现在在Page_Load 中,您可以检查Session("VerifiedHuman") = "True" 并相应地更新您的页面控件,隐藏带有验证码控件的面板并显示其他适当的项目。

    请注意,这会从Web.config 获取密钥,即

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

    【讨论】:

      【解决方案4】:

      这增加了一些东西。它将来自 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
      

      所以在按钮的 Click 事件中,只需调用:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-02-25
        • 1970-01-01
        • 2022-01-19
        • 1970-01-01
        • 2018-07-01
        • 2018-04-11
        相关资源
        最近更新 更多