Web API 2 c# 中的 Google reCaptcha

Posted

技术标签:

【中文标题】Web API 2 c# 中的 Google reCaptcha【英文标题】:Google reCaptcha in Web API 2 c# 【发布时间】:2017-09-05 17:43:39 【问题描述】:

我有一个 ASP.NET Web API 2 项目。我正在尝试从表单中读取 Google Captcha。 我试过这个代码:

    public string Post(FoundingRequest model)
    
        var response = Request["g-recaptcha-response"];
        string secretKey = "my key";
        var client = new WebClient();
        var result = client.DownloadString(
        $"https://www.google.com/recaptcha/api/siteverify?secret=secretKey&response=response");
        var obj = JObject.Parse(result);
        model.Captcha = (bool)obj.SelectToken("success");
        ....
    

但我在第一行收到一个错误:

无法将 [] 索引应用于类型表达式 'HttpRequestMessage'

为什么?以及如何解决?谢谢

【问题讨论】:

【参考方案1】:

该方法的主体对我来说效果很好:

 const string secretKey = "YOUR KEY";
            string responseFromServer = "";

            HttpWebRequest req = (HttpWebRequest)WebRequest.Create("https://www.google.com/recaptcha/api/siteverify?secret=" + secretKey + "&response=" + response);

            using (WebResponse resp = req.GetResponse())
            using (Stream dataStream = resp.GetResponseStream())
            
                if (dataStream != null)
                
                    using (StreamReader reader = new StreamReader(dataStream))
                    
                        // Read the content.
                        responseFromServer = reader.ReadToEnd();
                    
                
            

            dynamic jsonResponse = new javascriptSerializer().DeserializeObject(responseFromServer);

            return jsonResponse == null || bool.Parse(jsonResponse["success"].ToString());

更新

关于评论,可以在客户端查看

var response = window.grecaptcha.getResponse()

然后将这个变量传递给Web API

这是我的客户端脚本的一部分:

      if (typeof window.grecaptcha != 'undefined') 
        var capResponse = window.grecaptcha.getResponse();

        if (!capResponse || capResponse.length === 0) 
            user.isCaptchaPassed = false;
            //alert("Captcha not Passed");
            return false;
        

        user.gReCaptcha = capResponse;
    

“user”是之前创建的JS对象,通过JS传递给服务器。 (AJAX 调用)

【讨论】:

问题出在这一行:var response = Request["g-recaptcha-response"]; 检查更新。它应该适用于 JS 和 Web API【参考方案2】:

这就是我的做法。我不使用挑战,所以我没有打扰 试图弄清楚为什么它没有正确转换为 DateTime 。 也许其他人已经解决了这个问题。

   public class ReCaptchaResponse
        
            public bool Success;
            public string ChallengeTs;
            public string Hostname;
            public object[] ErrorCodes;
        

        [HttpPost]
        [Route("captcha")]
        public bool Captcha([FromBody] string token)
        
            bool isHuman = true;

            try
            
                string secretKey = ConfigurationManager.AppSettings["reCaptchaPrivateKey"];
                Uri uri = new Uri("https://www.google.com/recaptcha/api/siteverify" +
                                  $"?secret=secretKey&response=token");
                HttpWebRequest request = WebRequest.CreateHttp(uri);
                request.Method = "POST";
                request.ContentType = "application/x-www-form-urlencoded";
                request.ContentLength = 0;
                HttpWebResponse response = (HttpWebResponse) request.GetResponse();
                Stream responseStream = response.GetResponseStream();
                StreamReader streamReader = new StreamReader(responseStream);
                string result = streamReader.ReadToEnd();
                ReCaptchaResponse reCaptchaResponse = JsonConvert.DeserializeObject<ReCaptchaResponse>(result);
                isHuman = reCaptchaResponse.Success;
            
            catch (Exception ex)
            
                Trace.WriteLine("reCaptcha error: " + ex);
            

            return isHuman;
        

【讨论】:

【参考方案3】:

我找到了答案,我创建了一个具有特定名称的隐藏输入,并在 Captcha 回调中更新了它的值。代码:

   <input type="hidden" value="" id="recaptcha" name="recaptcha" />
   <div class="g-recaptcha" data-callback="imNotARobot" data-sitekey="key"></div>

而 Javascript 是:

<script type="text/javascript">
    var imNotARobot = function () 
       $("#recaptcha").val(grecaptcha.getResponse());
    ;
</script>

服务器端:

public string Recaptcha  get; set; 

模型绑定器完成所有工作。

【讨论】:

【参考方案4】:

我假设这个请求来自一个表单,更改这个:

var response = Request["g-recaptcha-response"];

至此:

var response = Request.Form["g-Recaptcha-Response"];

也改变这个:

var result = client.DownloadString($"https://www.google.com/recaptcha/api/siteverify?secret=secretKey&response=response");

至此:

var result = client.DownloadString(string.Format("https://www.google.com/recaptcha/api/siteverify?secret=0&response=1", secretKey, response));

【讨论】:

请再次阅读问题。问题在于: var response = Request["g-recaptcha-response"];问题中提到的错误消息的第一行 Web Api 2 请求中没有表单 验证码在哪里?在 MVC 页面上?您需要在 MVC 控制器中验证 ReCaptcha,然后调用 API。 它在纯 html 和 javascript 上。没有服务器端 它不会那样工作。您需要在 Web 应用程序中执行服务器端检查。由于 API 无法从标记中收集所需的其他信息,例如站点密钥。

以上是关于Web API 2 c# 中的 Google reCaptcha的主要内容,如果未能解决你的问题,请参考以下文章

C# 中的 Google 语音转文本 API

无法从 C# 中的 google api 令牌验证器获取数据

使用 Google Data API 使用 C# 访问 Google 电子表格

是否有 Java、C#、Python 或 Ruby 中的 Google Contacts API 的 Hello World 示例?

如何在 C# 中使用带有服务帐户的 gmail api 或 google Oauth 来发送邮件?

Google Analytics 嵌入 API 服务器端授权未使用 C# 呈现图表