如何在 ASP.NET 中实施 reCaptcha V3
How to implement reCaptcha V3 in ASP.NET
有人在 ASP.NET 中有完整的 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;
}
}
在 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>
Edit : I have added a demo project . Check this github repository .
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>
参考资料link:
https://developers.google.com/recaptcha/docs/verify
https://developers.google.com/recaptcha/docs/display#js_api
现在,在 aspx.cs 中,您需要编写一个“[WebMethod]”来接收来自 Ajax 请求的令牌。
[WebMethod]
public static void CaptchaVerify(string token)
{
var responseString = RecaptchaVerify(token);
ResponseToken response = new ResponseToken();
response = Newtonsoft.Json.JsonConvert.DeserializeObject<ResponseToken>(responseString.Result);
}
要从 google recapcha api 获得响应,您需要使用 httpClient 使用异步调用。您还需要创建一个 class ,它将包含与响应字符串相同的属性。获得 "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; }
}
最简单的实现:
在您的 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>
}
在您的 cshtml
表格内(就在 </form>
之前):
<input type="hidden" id="foo" name="foo" />
你的 Pagemodel
class 中的一个函数。响应对象见the documentation:
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" || JSONdata.score <= 0.5m)
{
return false;
}
return true;
}
最后,在您的 OnPostAsync()
处理程序中,在顶部:
if (!ModelState.IsValid)
{
return Page();
}
else
{
if (!ReCaptchaPassed(Request.Form["foo"]))
{
ModelState.AddModelError(string.Empty, "You failed the CAPTCHA.");
return Page();
}
}
有几个 Recaptcha 库可用于 ASP.Net。我选择使用 reCAPTCHA.AspNetCore because it provides an HtmlHelper.
请注意,此库仅支持每页一个 ReCatpcha,不支持非表单页面的 Recaptcha v3 被动监控。
本页接受的答案完全错误!!! Google returns 一个介于 0 和 1 之间的分数,表示提交内容可能是机器人还是可能是人类。
返回的success
属性只表示recaptcha token处理正确
应该检查的是score
属性,而不是success
属性
这些线是问题所在
if (JSONdata.success != "true")
return false;
return true;
要比较的实际分数可能在一个变量中,可以根据需要进行调整。 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;
当然,您可能希望在此答案中添加日志记录等,但这是所需的基本逻辑。
已接受的答案未遵循 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
});
});
}
服务器
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);
}
}
}
你可以这样称呼它..
var reCaptchaTask = GoogleReCaptcha.ReCaptchaPassed(Settings.GoogleReCaptcha.secret_key, SearchReq.gRecaptchaToken, "search");
确保将密钥放在设置文件中,而不是代码中。
有人在 ASP.NET 中有完整的 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;
}
}
在 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>
Edit : I have added a demo project . Check this github repository . 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>
参考资料link: https://developers.google.com/recaptcha/docs/verify https://developers.google.com/recaptcha/docs/display#js_api
现在,在 aspx.cs 中,您需要编写一个“[WebMethod]”来接收来自 Ajax 请求的令牌。
[WebMethod]
public static void CaptchaVerify(string token)
{
var responseString = RecaptchaVerify(token);
ResponseToken response = new ResponseToken();
response = Newtonsoft.Json.JsonConvert.DeserializeObject<ResponseToken>(responseString.Result);
}
要从 google recapcha api 获得响应,您需要使用 httpClient 使用异步调用。您还需要创建一个 class ,它将包含与响应字符串相同的属性。获得 "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; }
}
最简单的实现:
在您的
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> }
在您的
cshtml
表格内(就在</form>
之前):<input type="hidden" id="foo" name="foo" />
你的
Pagemodel
class 中的一个函数。响应对象见the documentation: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" || JSONdata.score <= 0.5m) { return false; } return true; }
最后,在您的
OnPostAsync()
处理程序中,在顶部:if (!ModelState.IsValid) { return Page(); } else { if (!ReCaptchaPassed(Request.Form["foo"])) { ModelState.AddModelError(string.Empty, "You failed the CAPTCHA."); return Page(); } }
有几个 Recaptcha 库可用于 ASP.Net。我选择使用 reCAPTCHA.AspNetCore because it provides an HtmlHelper.
请注意,此库仅支持每页一个 ReCatpcha,不支持非表单页面的 Recaptcha v3 被动监控。
本页接受的答案完全错误!!! Google returns 一个介于 0 和 1 之间的分数,表示提交内容可能是机器人还是可能是人类。
返回的success
属性只表示recaptcha token处理正确
应该检查的是score
属性,而不是success
属性
这些线是问题所在
if (JSONdata.success != "true")
return false;
return true;
要比较的实际分数可能在一个变量中,可以根据需要进行调整。 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;
当然,您可能希望在此答案中添加日志记录等,但这是所需的基本逻辑。
已接受的答案未遵循 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
});
});
}
服务器
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);
}
}
}
你可以这样称呼它..
var reCaptchaTask = GoogleReCaptcha.ReCaptchaPassed(Settings.GoogleReCaptcha.secret_key, SearchReq.gRecaptchaToken, "search");
确保将密钥放在设置文件中,而不是代码中。