如何在ASP.NET中实现reCaptcha V3

Tig*_*g7r 6 asp.net recaptcha recaptcha-v3

是否有人在ASP.NET中具有reCaptcha V3的完整实现演示?

我找到了这篇文章:Google Recaptcha v3示例演示

目前,我正在使用带有以下代码的reCaptcha V2:

public bool RecaptchaValidate()
    {
        string Response = Request.Form["g-recaptcha-response"];//Getting Response String Append to Post Method
        bool Valid = false;
        //Request to Google Server
        var CaptchaSiteKey = Settings["NewUserRegCaptchaSecretSiteKey"].ToString();
        HttpWebRequest req = (HttpWebRequest)WebRequest.Create
        (" https://www.google.com/recaptcha/api/siteverify?secret=" + CaptchaSiteKey + "&response=" + Response);
        try
        {
            //Google recaptcha Response
            using (WebResponse wResponse = req.GetResponse())
            {

                using (StreamReader readStream = new StreamReader(wResponse.GetResponseStream()))
                {
                    string jsonResponse = readStream.ReadToEnd();

                    JavaScriptSerializer js = new JavaScriptSerializer();
                    ReCaptchaObject data = js.Deserialize<ReCaptchaObject>(jsonResponse);// Deserialize Json

                    Valid = Convert.ToBoolean(data.success);
                }
            }

            return Valid;
        }
        catch (WebException ex)
        {
            throw ex;
        }
    }
Run Code Online (Sandbox Code Playgroud)

在view.ascx页面上,我有:

<%@ Register TagPrefix="recaptcha" Namespace="Recaptcha" Assembly="Recaptcha" %>

<script src='https://www.google.com/recaptcha/api.js'></script>

<scrip>
var recap = grecaptcha.getResponse();
if (recap.length == 0) {
                $("#verifyhuman").css("display", "block");
            }
</script>

 <div class="g-recaptcha" data-sitekey="<%=ReCaptchaPublicKey%>" id="recaptcha" data-callback="recaptchaCallback"></div>
Run Code Online (Sandbox Code Playgroud)

小智 14

最简单的:

a)在cshtml中(在顶部)

@section Scripts
{
    <script src="https://www.google.com/recaptcha/api.js?render=your site key"></script>
    <script>
        grecaptcha.ready(function () {
            grecaptcha.execute('your site key', { action: 'homepage' }).then(function (token) {
                document.getElementById("foo").value = token;
            });
        });
 </script>
}
Run Code Online (Sandbox Code Playgroud)

b)在表单内部的cshtml中(就在/ form>之前:

@section Scripts
{
    <script src="https://www.google.com/recaptcha/api.js?render=your site key"></script>
    <script>
        grecaptcha.ready(function () {
            grecaptcha.execute('your site key', { action: 'homepage' }).then(function (token) {
                document.getElementById("foo").value = token;
            });
        });
 </script>
}
Run Code Online (Sandbox Code Playgroud)

c)Pagemodel类中的一个函数:

    <input type="hidden" id="foo" name="foo" />
Run Code Online (Sandbox Code Playgroud)

最后,在开始的OnPostAsync内部:

        public static bool ReCaptchaPassed(string gRecaptchaResponse)
        {
            HttpClient httpClient = new HttpClient();
            var res = httpClient.GetAsync($"https://www.google.com/recaptcha/api/siteverify?secret=your secret key no quotes&response={gRecaptchaResponse}").Result;
            if (res.StatusCode != HttpStatusCode.OK)
                return false;

            string JSONres = res.Content.ReadAsStringAsync().Result;
            dynamic JSONdata = JObject.Parse(JSONres);
            if (JSONdata.success != "true")
                return false;

            return true;
        }
Run Code Online (Sandbox Code Playgroud)

  • 请小心 HttpClient 的使用。这样它就会耗尽服务器上的套接字。https://www.thecodebuzz.com/using-httpclient-best-practices-and-anti-patterns/ (3认同)
  • 我让这个工作,但一些补充:你没有提到添加“表单提交按钮”(可能假设)。我还必须反序列化响应 JSON。 (2认同)

win*_*yip 9

本页接受的答案完全错误!Google 返回 0 到 1 之间的分数,以表明提交的内容可能是机器人还是人类。

返回的属性success仅意味着验证码令牌已正确处理。

score应该检查的是财产,而不是success财产

这些行是问题所在

if (JSONdata.success != "true")
    return false;

return true;
Run Code Online (Sandbox Code Playgroud)

要比较的实际分数可能是一个可以根据需要进行调整的变量。Google 建议从 0.5 开始。

所以代码应该改为:

var recaptchaScore = 0.5m; // this could be in appSettings or whereever/however you are storing your constants

if (JSONdata.success != "true" || JSONdata.score <= recaptchaScore)
    return false;

return true;
Run Code Online (Sandbox Code Playgroud)

当然,您可能希望在这个答案中添加日志记录等,但这是所需的简单逻辑。


Nih*_*kar 8

编辑:我已经添加了一个演示项目。检查这个github仓库。 https://github.com/NIHAR-SARKAR/GoogleRecaptchav3-example-In-asp.net

从前端(.aspx页面),您需要发送ajax请求,以将令牌传递给后端服务器。使用“ recaptcha.execute”,U可以获取响应,并使用ajax请求传递令牌。请检查代码块。

 <script src="http://www.google.com/recaptcha/api.js?render=recaptchaSiteKey"></script>
<script>
 grecaptcha.ready(function() {
 grecaptcha.execute('recaptchaSiteKey', {action: 'homepage'}).then(function(token) {

            $.ajax({
                //pass the toket to Webmethod using Ajax
            });
          });
     });
</script>
Run Code Online (Sandbox Code Playgroud)

参考链接:https : //developers.google.com/recaptcha/docs/verify https://developers.google.com/recaptcha/docs/display#js_api

现在,在aspx.cs中,您需要编写一个[WebMethod]来从Ajax request接收令牌。

    [WebMethod]
    public static void CaptchaVerify(string token)
    {
            var responseString = RecaptchaVerify(token);
            ResponseToken response = new ResponseToken();
            response = Newtonsoft.Json.JsonConvert.DeserializeObject<ResponseToken>(responseString.Result);

    }
Run Code Online (Sandbox Code Playgroud)

要从google recapcha api获得响应,您需要使用httpClient使用异步调用。您还需要创建一个类,该类将包含相同的属性,例如响应字符串。获取“ responseString”后,您需要使用Newtonsoft.Json将响应转换为ResponseToken对象。 response = Newtonsoft.Json.JsonConvert.DeserializeObject<ResponseToken>(responseString.Result);

private string apiAddress = "https://www.google.com/recaptcha/api/siteverify";

private string recaptchaSecret = googleRecaptchaSecret;

        public async Task<string> RecaptchaVerify(string recaptchaToken)
        {
            string url = $"{apiAddress}?secret={recaptchaSecret}&response={recaptchaToken}";
            using (var httpClient = new HttpClient())
            {
                try
                {

                    string responseString=  httpClient.GetStringAsync(url).Result;
                    return responseString;

                }
                catch (Exception ex)
                {
                    throw new Exception(ex.Message);
                }
            }
        }


        public class ResponseToken
        {

            public DateTime challenge_ts { get; set; }
            public float score { get; set; }
            public List<string> ErrorCodes { get; set; }
            public bool Success { get; set; }
            public string hostname { get; set; }
        }
Run Code Online (Sandbox Code Playgroud)

  • 请小心 HttpClient 的使用。这样它就会耗尽服务器上的套接字。https://www.thecodebuzz.com/using-httpclient-best-practices-and-anti-patterns/ (2认同)

Don*_* V. 2

接受的答案不遵循 Google 发送响应和检查操作的规范。它的 Http 请求也会耗尽套接字数量。这是我的实现。

浏览器

// Could be called from an event or another piece of code.
function FunctionToCall(term) {

    // Google reCaptcha check
    grecaptcha.ready(function() {
        grecaptcha.execute(reCaptchaSiteKey, {action: "search"}).then(function(token) {

            // You can take the response token Google returns, check it server side using
            // the GoogleReCaptcha class and respond with a pass or fail. If a pass, run a block of code client side.
            // { ... block of code ... }
            
            // Or if you want to secure an endpoint that your sending request too. 
            // Send the response token with the request to your endpoint and check the response token server side and respond with a pass or fail.
            // Use the repsonse to show a message or redirect site, etc

        });
    });

}
Run Code Online (Sandbox Code Playgroud)

服务器

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;

public class GoogleReCaptcha
{
    public class ReCaptchaResponse
    {
        public bool success { get; set; }
        public double score { get; set; }
        public string action { get; set; }
        public DateTime challenge_ts { get; set; }
        public string hostname { get; set; }
        [JsonProperty("error-codes")]
        public List<string> error_codes { get; set; }
    }

    public static async Task<(ReCaptchaResponse Response, bool HasPassed)> ReCaptchaPassed(string secretKey, string gRecaptchaToken, string expected_action)
    {
        try
        {
            // validate 
            if (string.IsNullOrWhiteSpace(secretKey) || string.IsNullOrWhiteSpace(gRecaptchaToken) || string.IsNullOrWhiteSpace(expected_action))
                return (null, false);

            // we use HttpClientFactory to avoid exhausting number of sockets available
            var httpClient = HttpClientFactory.Create();

            var verifyUrl = "https://www.google.com/recaptcha/api/siteverify";
            var parameters = new Dictionary<string, string>
            {
                {"secret", secretKey},
                {"response", gRecaptchaToken}
                //{"remoteip", "ip" } <= this is optional
            };
            using (HttpContent formContent = new FormUrlEncodedContent(parameters))
            {
                using (var response = await httpClient.PostAsync(verifyUrl, formContent).ConfigureAwait(false))
                {
                    // check HTTP response code
                    if (response.StatusCode != HttpStatusCode.OK)
                        return (null, false);

                    // get reCaptcha response
                    string gRecaptchaJsonresult = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
                    if (string.IsNullOrWhiteSpace(gRecaptchaJsonresult))
                        return (null, false);


                    // check reCaptcha response is successful
                    var recaptcha_response = JsonConvert.DeserializeObject<ReCaptchaResponse>(gRecaptchaJsonresult);
                    if (recaptcha_response == null)
                    {
                        //Logging.Log(new Logging.LogItem { Msg = $"Google RecCaptcha response is null" }, DefaultLogValues);
                        return (recaptcha_response, false);
                    }

                    if (!recaptcha_response.success)
                    {
                        var errors = string.Join(",", recaptcha_response.error_codes);
                        //Logging.Log(new Logging.LogItem { Msg = $"Google RecCaptcha error codes:\n{errors}" }, DefaultLogValues);
                        return (recaptcha_response, false);
                    }

                    // check reCaptcha response action
                    if (recaptcha_response.action.ToUpper() != expected_action.ToUpper())
                    {
                        //Logging.Log(new Logging.LogItem { Msg = $"Google RecCaptcha action doesn't match:\nExpected action: {expected_action} Given action: {recaptcha_response.action}" }, DefaultLogValues);
                        return (recaptcha_response, false);
                    }

                    // response score
                    // anything less than 0.5 is a bot
                    if (recaptcha_response.score < 0.5)
                        return (recaptcha_response, false);
                    else
                        return (recaptcha_response, true);
                }
            }
        }
        catch (Exception ex)
        {
            //Logging.Log(ex, DefaultLogValues);

            // default to false
            return (null, false);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

你会这样称呼它..

var reCaptchaTask = GoogleReCaptcha.ReCaptchaPassed(Settings.GoogleReCaptcha.secret_key, SearchReq.gRecaptchaToken, "search");
Run Code Online (Sandbox Code Playgroud)

确保将密钥放在设置文件中而不是代码中。