The new Recaptcha 2看起来很有希望,但我没有找到在ASP.NET服务器端验证它的方法,
This answer中的 if(Page.IsValid)
,对旧的Recaptcha有效,但不适用于新的,
如何在服务器端验证新的reCAPTCHA?
答案 0 :(得分:137)
在阅读了很多资源之后,我最后编写了这个类来处理the new ReCaptcha的验证:
如上所述Here:当最终用户解决reCAPTCHA时,将在HTML中填充新字段(g-recaptcha-response)。
我们需要读取此值并将其传递给下面的类来验证它:
在C#中:
在您网页背后的代码中:
string EncodedResponse = Request.Form["g-Recaptcha-Response"];
bool IsCaptchaValid = (ReCaptchaClass.Validate(EncodedResponse) == "true" ? true : false);
if (IsCaptchaValid) {
//Valid Request
}
班级:
using Newtonsoft.Json;
public class ReCaptchaClass
{
public static string Validate(string EncodedResponse)
{
var client = new System.Net.WebClient();
string PrivateKey = "6LcH-v8SerfgAPlLLffghrITSL9xM7XLrz8aeory";
var GoogleReply = client.DownloadString(string.Format("https://www.google.com/recaptcha/api/siteverify?secret={0}&response={1}", PrivateKey, EncodedResponse));
var captchaResponse = Newtonsoft.Json.JsonConvert.DeserializeObject<ReCaptchaClass>(GoogleReply);
return captchaResponse.Success.ToLower();
}
[JsonProperty("success")]
public string Success
{
get { return m_Success; }
set { m_Success = value; }
}
private string m_Success;
[JsonProperty("error-codes")]
public List<string> ErrorCodes
{
get { return m_ErrorCodes; }
set { m_ErrorCodes = value; }
}
private List<string> m_ErrorCodes;
}
在VB.NET中:
在您网页背后的代码中:
Dim EncodedResponse As String = Request.Form("g-Recaptcha-Response")
Dim IsCaptchaValid As Boolean = IIf(ReCaptchaClass.Validate(EncodedResponse) = "True", True, False)
If IsCaptchaValid Then
'Valid Request
End If
班级:
Imports Newtonsoft.Json
Public Class ReCaptchaClass
Public Shared Function Validate(ByVal EncodedResponse As String) As String
Dim client = New System.Net.WebClient()
Dim PrivateKey As String = "6dsfH-v8SerfgAPlLLffghrITSL9xM7XLrz8aeory"
Dim GoogleReply = client.DownloadString(String.Format("https://www.google.com/recaptcha/api/siteverify?secret={0}&response={1}", PrivateKey, EncodedResponse))
Dim captchaResponse = Newtonsoft.Json.JsonConvert.DeserializeObject(Of ReCaptchaClass)(GoogleReply)
Return captchaResponse.Success
End Function
<JsonProperty("success")> _
Public Property Success() As String
Get
Return m_Success
End Get
Set(value As String)
m_Success = value
End Set
End Property
Private m_Success As String
<JsonProperty("error-codes")> _
Public Property ErrorCodes() As List(Of String)
Get
Return m_ErrorCodes
End Get
Set(value As List(Of String))
m_ErrorCodes = value
End Set
End Property
Private m_ErrorCodes As List(Of String)
End Class
答案 1 :(得分:41)
这是一个使用JavaScriptSerializer的版本。感谢Ala提供此代码的基础。
WebConfig App设置 - 在我的案例中,我已将密钥添加到Web.Config中,以允许在环境之间进行转换。如果需要,它也可以在这里轻松加密。
<add key="Google.ReCaptcha.Secret" value="123456789012345678901234567890" />
ReCaptcha类 - 一个简单的类,可将响应参数以及您的秘密发布到Google并对其进行验证。响应使用.Net JavaScriptSerializer类反序列化,并返回true或false。
using System.Collections.Generic;
using System.Configuration;
public class ReCaptcha
{
public bool Success { get; set; }
public List<string> ErrorCodes { get; set; }
public static bool Validate(string encodedResponse)
{
if (string.IsNullOrEmpty(encodedResponse)) return false;
var client = new System.Net.WebClient();
var secret = ConfigurationManager.AppSettings["Google.ReCaptcha.Secret"];
if (string.IsNullOrEmpty(secret)) return false;
var googleReply = client.DownloadString(string.Format("https://www.google.com/recaptcha/api/siteverify?secret={0}&response={1}", secret, encodedResponse));
var serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
var reCaptcha = serializer.Deserialize<ReCaptcha>(googleReply);
return reCaptcha.Success;
}
}
验证响应 - 检查Controller中g-Recaptcha-Response表单参数的有效性(或Web表单后面的代码)并采取适当的措施。
var encodedResponse = Request.Form["g-Recaptcha-Response"];
var isCaptchaValid = ReCaptcha.Validate(encodedResponse);
if (!isCaptchaValid)
{
// E.g. Return to view or set an error message to visible
}
答案 2 :(得分:13)
这些答案中的大多数似乎比需要的更复杂。他们也没有指定有助于防止拦截攻击的IP(https://security.stackexchange.com/questions/81865/is-there-any-reason-to-include-the-remote-ip-when-using-recaptcha)。这就是我坚持的原因
public bool CheckCaptcha(string captchaResponse, string ipAddress)
{
using (var client = new WebClient())
{
var response = client.DownloadString($"https://www.google.com/recaptcha/api/siteverify?secret={ ConfigurationManager.AppSettings["Google.ReCaptcha.Secret"] }&response={ captchaResponse }&remoteIp={ ipAddress }");
return (bool)JObject.Parse(response)["success"];
}
}
答案 3 :(得分:6)
您可以使用“IsValidCaptcha()”方法在服务器端验证您的google recaptcha。使用以下方法中的“YourRecaptchaSecretkey”替换您的密钥。
Public bool IsValidCaptcha()
{
string resp = Request["g-recaptcha-response"];
var req = (HttpWebRequest)WebRequest.Create
(https://www.google.com/recaptcha/api/siteverify?secret=+ YourRecaptchaSecretkey + "&response=" + resp);
using (WebResponse wResponse = req.GetResponse())
{
using (StreamReader readStream = new StreamReader(wResponse.GetResponseStream()))
{
string jsonResponse = readStream.ReadToEnd();
JavaScriptSerializer js = new JavaScriptSerializer();
// Deserialize Json
CaptchaResult data = js.Deserialize<CaptchaResult>(jsonResponse);
if (Convert.ToBoolean(data.success))
{
return true;
}
}
}
return false;
}
同时创建以下课程。
public class CaptchaResult
{
public string success { get; set; }
}
参考link
答案 4 :(得分:3)
根据doc,您只需发布您的密钥和用户对API的回答,然后阅读返回&#34;成功&#34;属性
简短的答案:
var webClient = new WebClient();
string verification = webClient.DownloadString(string.Format("https://www.google.com/recaptcha/api/siteverify?secret={0}&response={1}", secretKey, userResponse));
if (JObject.Parse(verification)["success"].Value<bool>())
{
// SUCCESS!!!
完整示例:
假设您在 IamNotARobotLogin.cshtml 中实施了this页面。
<head>
<script src="https://www.google.com/recaptcha/api.js" async defer></script>
</head>
<body>
<form action="Login" method="POST">
<div class="g-recaptcha" data-sitekey="your_site_key"></div><br/>
<input type="submit" value="Log In">
</form>
</body>
假设你希望控制器保存,让我们说,&#34; I_AM_NOT_ROBOT&#34;如果验证成功,则在会话中标记:
public ActionResult IamNotARobotLogin()
{
return View();
}
[HttpPost]
public ActionResult Login()
{
const string secretKey = "6LcH-v8SerfgAPlLLffghrITSL9xM7XLrz8aeory";
string userResponse = Request.Form["g-Recaptcha-Response"];
var webClient = new System.Net.WebClient();
string verification = webClient.DownloadString(string.Format("https://www.google.com/recaptcha/api/siteverify?secret={0}&response={1}", secretKey, userResponse));
var verificationJson = Newtonsoft.Json.Linq.JObject.Parse(verification);
if (verificationJson["success"].Value<bool>())
{
Session["I_AM_NOT_A_ROBOT"] = "true";
return RedirectToAction("Index", "Demo");
}
// try again:
return RedirectToAction("IamNotARobotLogin");
}
答案 5 :(得分:3)
以下是我的解决方案,以便:
在控制器中:
bool isCaptchaValid = await ReCaptchaClass.Validate(this.Request);
if (!isCaptchaValid)
{
ModelState.AddModelError("", "Invalid captcha");
return View(model);
}
实用程序类:
public class ReCaptchaClass
{
private static ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
private static string SecretKey = System.Configuration.ConfigurationManager.AppSettings["Google.ReCaptcha.Secret"];
[JsonProperty("success")]
public bool Success { get; set; }
[JsonProperty("error-codes")]
public List<string> ErrorCodes { get; set; }
public static async Task<bool> Validate(HttpRequestBase Request)
{
string encodedResponse = Request.Form["g-Recaptcha-Response"];
string remoteIp = Request.UserHostAddress;
using (var client = new HttpClient())
{
var values = new Dictionary<string, string>
{
{"secret", SecretKey},
{"remoteIp", remoteIp},
{"response", encodedResponse}
};
var content = new FormUrlEncodedContent(values);
var response = await client.PostAsync("https://www.google.com/recaptcha/api/siteverify", content);
var responseString = await response.Content.ReadAsStringAsync();
var captchaResponse = Newtonsoft.Json.JsonConvert.DeserializeObject<ReCaptchaClass>(responseString);
if ((captchaResponse.ErrorCodes?.Count ?? 0) != 0)
{
log.Warn("ReCaptcha errors: " + string.Join("\n", captchaResponse.ErrorCodes));
}
return captchaResponse.Success;
}
}
}
答案 6 :(得分:1)
另一个例子发布在这里:
它还实现了Recaptcha 2.0的安全令牌选项(查看该位的完整源代码,我已经删除了相关的代码片段,仅用于验证结果)。
这个不依赖于newtonsoft的json解析器,而是使用内置的.NET解析器。
以下是RecaptchaV2.NET库(来自recaptcha.cs)的相关代码片段:
namespace RecaptchaV2.NET
{
/// <summary>
/// Helper Methods for the Google Recaptcha V2 Library
/// </summary>
public class Recaptcha
{
public string SiteKey { get; set; }
public string SecretKey { get; set; }
public Guid SessionId { get; set; }
/// <summary>
/// Validates a Recaptcha V2 response.
/// </summary>
/// <param name="recaptchaResponse">g-recaptcha-response form response variable (HttpContext.Current.Request.Form["g-recaptcha-response"])</param>
/// <returns>RecaptchaValidationResult</returns>
public RecaptchaValidationResult Validate(string recaptchaResponse)
{
RecaptchaValidationResult result = new RecaptchaValidationResult();
HttpWebRequest req = (HttpWebRequest)WebRequest.Create("https://www.google.com/recaptcha/api/siteverify?secret=" + SecretKey + "&response="
+ recaptchaResponse + "&remoteip=" + GetClientIp());
//Google recaptcha Response
using (WebResponse wResponse = req.GetResponse())
{
using (StreamReader readStream = new StreamReader(wResponse.GetResponseStream()))
{
string jsonResponse = readStream.ReadToEnd();
JavaScriptSerializer js = new JavaScriptSerializer();
result = js.Deserialize<RecaptchaValidationResult>(jsonResponse.Replace("error-codes", "ErrorMessages").Replace("success", "Succeeded"));// Deserialize Json
}
}
return result;
}
private string GetClientIp()
{
// Look for a proxy address first
String _ip = HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
// If there is no proxy, get the standard remote address
if (string.IsNullOrWhiteSpace(_ip) || _ip.ToLower() == "unknown")
_ip = HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
return _ip;
}
}
public class RecaptchaValidationResult
{
public RecaptchaValidationResult()
{
ErrorMessages = new List<string>();
Succeeded = false;
}
public List<string> ErrorMessages { get; set; }
public bool Succeeded { get; set; }
public string GetErrorMessagesString()
{
return string.Join("<br/>", ErrorMessages.ToArray());
}
}
}
答案 7 :(得分:1)
Google的ReCaptcha API不再接受有效负载作为GET请求中的查询字符串参数。除非我通过HTTP POST发送数据,否则Google总是会返回“错误”的成功回复。以下是对Ala(优秀!)类的更新,该类将有效负载发布到Google服务端点:
using Newtonsoft.Json;
using System.Net;
using System.IO;
using System.Text;
public class RecaptchaHandler
{
public static string Validate(string EncodedResponse, string RemoteIP)
{
var client = new WebClient();
string PrivateKey = "PRIVATE KEY";
WebRequest req = WebRequest.Create("https://www.google.com/recaptcha/api/siteverify");
string postData = String.Format("secret={0}&response={1}&remoteip={2}",
PrivateKey,
EncodedResponse,
RemoteIP);
byte[] send = Encoding.Default.GetBytes(postData);
req.Method = "POST";
req.ContentType = "application/x-www-form-urlencoded";
req.ContentLength = send.Length;
Stream sout = req.GetRequestStream();
sout.Write(send, 0, send.Length);
sout.Flush();
sout.Close();
WebResponse res = req.GetResponse();
StreamReader sr = new StreamReader(res.GetResponseStream());
string returnvalue = sr.ReadToEnd();
var captchaResponse = JsonConvert.DeserializeObject<RecaptchaHandler>(returnvalue);
return captchaResponse.Success;
}
[JsonProperty("success")]
public string Success
{
get { return m_Success; }
set { m_Success = value; }
}
private string m_Success;
[JsonProperty("error-codes")]
public List<string> ErrorCodes
{
get { return m_ErrorCodes; }
set { m_ErrorCodes = value; }
}
private List<string> m_ErrorCodes;
}
答案 8 :(得分:0)
使用dynamic验证服务器端的recaptcha
调用函数
[HttpPost]
public ActionResult ClientOrderDetail(FormCollection collection, string EncodedResponse)
{
Boolean Validation = myFunction.ValidateRecaptcha(EncodedResponse);
return View();
}
功能声明
public static Boolean ValidateRecaptcha(string EncodedResponse)
{
string PrivateKey = "YourSiteKey";
var client = new System.Net.WebClient();
var GoogleReply = client.DownloadString(string.Format("https://www.google.com/recaptcha/api/siteverify?secret={0}&response={1}", PrivateKey, EncodedResponse));
var serializer = new JavaScriptSerializer();
dynamic data = serializer.Deserialize(GoogleReply, typeof(object));
Boolean Status = data["success"];
string challenge_ts = data["challenge_ts"];
string hostname = data["hostname"];
return Status;
}
答案 9 :(得分:0)
我在this so post中发布的示例使用Newtonsoft.JSON反序列化完整返回的JSON,将数据发布到Google(而不是使用查询字符串)将相关变量存储在web.config中而不是硬编码
答案 10 :(得分:0)
This article对如何在模型上实现ReCaptcha验证属性进行了清晰的分步说明。
首先,创建Recaptcha验证属性。
namespace Sample.Validation
{
public class GoogleReCaptchaValidationAttribute : ValidationAttribute
{
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
Lazy<ValidationResult> errorResult = new Lazy<ValidationResult>(() => new ValidationResult("Google reCAPTCHA validation failed", new String[] { validationContext.MemberName }));
if (value == null || String.IsNullOrWhiteSpace( value.ToString()))
{
return errorResult.Value;
}
IConfiguration configuration = (IConfiguration)validationContext.GetService(typeof(IConfiguration));
String reCaptchResponse = value.ToString();
String reCaptchaSecret = configuration.GetValue<String>("GoogleReCaptcha:SecretKey");
HttpClient httpClient = new HttpClient();
var httpResponse = httpClient.GetAsync($"https://www.google.com/recaptcha/api/siteverify?secret={reCaptchaSecret}&response={reCaptchResponse}").Result;
if (httpResponse.StatusCode != HttpStatusCode.OK)
{
return errorResult.Value;
}
String jsonResponse = httpResponse.Content.ReadAsStringAsync().Result;
dynamic jsonData = JObject.Parse(jsonResponse);
if (jsonData.success != true.ToString().ToLower())
{
return errorResult.Value;
}
return ValidationResult.Success;
}
}
}
然后在模型上添加验证属性。
namespace Sample.Models
{
public class XModel
{
// ...
[Required]
[GoogleReCaptchaValidation]
[BindProperty(Name = "g-recaptcha-response")]
public String GoogleReCaptchaResponse { get; set; }
}
}
最后,您只需调用ModelState.IsValid方法
namespace Sample.Api.Controllers
{
[ApiController]
public class XController : ControllerBase
{
[HttpPost]
public IActionResult Post(XModel model)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
// ...
}
}
}
等等! :)