这就是我使用 ASP.Net MVC 和 ReCaptcha 3 的方式。
- 在 Visual Studio 2015 或 2017 中,创建一个新的 ASP.NET MVC 项目并将目标 .NET Framework 设置为 4.6.2。
- 为您的 ASP.NET MVC 项目创建一个描述性名称(例如 ASPNetMVCWithReCaptcha3)。
- 构建您的应用程序并确保它可以编译并且没有错误。
- 在 Web.Config 中,创建两个新密钥,然后从保存这些引用的文本编辑器中复制/粘贴站点密钥和密钥。
<appSettings>
<add key="reCaptchaSiteKey" value="site_key" />
<add key="reCaptchaSecretKey" value="secret_key" />
</appSettings>
- 在“模型”文件夹中,创建一个新类“ReCaptchaForm.cs”并复制/粘贴以下代码行。
namespace ASPNetMVCWithReCaptcha3.Models
{
public class ReCaptchaForm
{
public string Message { get; set; }
}
}
- 在项目中创建一个新的“类”文件夹。
- 在“Classes”文件夹中,创建一个新类“ReCaptcha.cs”并复制/粘贴以下代码行:
using System;
using System.Web;
using System.Collections.Generic;
using System.Web.Mvc;
using System.Net.Http;
using System.Configuration;
namespace ASPNetMVCWithReCaptcha3.Classes
{
}
在命名空间内添加以下行
- 添加一个类“GoogleReCaptchaVariables”,它将存储呈现 ReCaptcha 所需的变量。
public static class GoogleReCaptchaVariables
{
public static string ReCaptchaSiteKey = ConfigurationManager.AppSettings["reCaptchaSiteKey"]?.ToString() ?? string.Empty;
public static string ReCaptchaSecretKey = ConfigurationManager.AppSettings["reCaptchaSecretKey"]?.ToString() ?? string.Empty;
public static string InputName = "g-recaptcha-response";
}
public static class ReCaptchaHelper
{
public static IHtmlString ReCaptchaHidden(this HtmlHelper helper)
{
var mvcHtmlString = new TagBuilder("input")
{
Attributes =
{
new KeyValuePair<string, string>("type", "hidden"),
new KeyValuePair<string, string>
("id", GoogleReCaptchaVariables.InputName),
new KeyValuePair<string, string>
("name", GoogleReCaptchaVariables.InputName)
}
};
string renderedReCaptchaInput =
mvcHtmlString.ToString(TagRenderMode.Normal);
return MvcHtmlString.Create($"{renderedReCaptchaInput}");
}
public static IHtmlString ReCaptchaJS
(this HtmlHelper helper, string useCase = "homepage")
{
string reCaptchaSiteKey = GoogleReCaptchaVariables.ReCaptchaSiteKey;
string reCaptchaApiScript = "<script
src='https://www.google.com/recaptcha/api.js?render=" +
reCaptchaSiteKey + "'></script>;";
string reCaptchaTokenResponseScript = "<script>
$('form').submit(function(e) { e.preventDefault();
grecaptcha.ready(function() { grecaptcha.execute('" +
reCaptchaSiteKey + "', {action: '" + useCase +
"'}).then(function(token) { $('#" +
GoogleReCaptchaVariables.InputName + "').val(token);
$('form').unbind('submit').submit(); }); }); }); </script>;";
return MvcHtmlString.Create
($"{reCaptchaApiScript}{reCaptchaTokenResponseScript}");
}
}
- 添加另一个呈现“span”标签的帮助器类,以在 ReCaptcha 验证失败时显示错误消息。
public static IHtmlString ReCaptchaValidationMessage
(this HtmlHelper helper, string errorText = null)
{
var invalidReCaptchaObj =
helper.ViewContext.Controller.TempData["InvalidCaptcha"];
var invalidReCaptcha = invalidReCaptchaObj?.ToString();
if (string.IsNullOrWhiteSpace(invalidReCaptcha))
return MvcHtmlString.Create("");
var buttonTag = new TagBuilder("span")
{
Attributes = {
new KeyValuePair<string, string>("class", "text-danger")
},
InnerHtml = errorText ?? invalidReCaptcha
};
return MvcHtmlString.Create(buttonTag.ToString(TagRenderMode.Normal));
}
- 接下来,创建一个属性“ValidateReCaptchaAttribute”来处理 API 调用。添加一个内部类“ResponseToken”来存储响应数据。然后,实现验证逻辑以在验证失败时显示错误消息。
public class ValidateReCaptchaAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
string reCaptchaToken =
filterContext.HttpContext.Request.Form[GoogleReCaptchaVariables.InputName];
string reCaptchaResponse = ReCaptchaVerify(reCaptchaToken);
ResponseToken response = new ResponseToken();
if (reCaptchaResponse != null)
{
response = Newtonsoft.Json.JsonConvert.DeserializeObject
(reCaptchaResponse);
}
if (!response.Success)
{
AddErrorAndRedirectToGetAction(filterContext);
}
base.OnActionExecuting(filterContext);
}
public string ReCaptchaVerify(string responseToken)
{
const string apiAddress =
"https://www.google.com/recaptcha/api/siteverify";
string recaptchaSecretKey = GoogleReCaptchaVariables.ReCaptchaSecretKey;
string urlToPost = $"{apiAddress}
?secret={recaptchaSecretKey}&response={responseToken}";
string responseString = null;
using (var httpClient = new HttpClient())
{
try
{
responseString = httpClient.GetStringAsync(urlToPost).Result;
}
catch
{
//Todo: Error handling process goes here
}
}
return responseString;
}
private static void AddErrorAndRedirectToGetAction
(ActionExecutingContext filterContext, string message = null)
{
filterContext.Controller.TempData["InvalidCaptcha"] =
message ?? "Invalid Captcha! The form cannot be submitted.";
filterContext.Result =
new RedirectToRouteResult(filterContext.RouteData.Values);
}
internal class ResponseToken
{
public bool Success { get; set; }
public float Score { get; set; }
public string Action { get; set; }
public DateTime Challenge_TS { get; set; }
public string HostName { get; set; }
public List ErrorCodes { get; set; }
}
}
- 在控制器中,创建一个实现 [ValidateReCaptcha] 属性的回发操作。
[HttpPost]
[ValidateAntiForgeryToken]
[ValidateReCaptcha]
public ActionResult Index(ReCaptchaForm form)
{
return View(form);
}
- 在您的控制器视图中,添加以下行以呈现表单、消息输入和提交底部。
@model ASPNetMVCWithReCaptcha3.Models.ReCaptchaForm
@using ASPNetMVCWithReCaptcha3.Classes;
@{
ViewBag.Title = "ReCaptcha Form";
}
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
@Html.LabelFor(model => model.Message)
@Html.TextAreaFor(model => model.Message, new { @class = "form-control" })
@Html.ReCaptchaValidationMessage()
@Html.ReCaptchaHidden()
@Html.ReCaptchaJS()
<button type="submit" class="btn btn-primary">Send Message</button>
}
- 构建项目并确保它没有错误。因此,如果 ReCaptcha API 返回成功响应,则应提交表单。相反,如果 API 返回失败的响应,则错误消息将显示在消息输入的底部。