Как реализовать reCaptcha для ASP.NET MVC?

Как реализовать reCaptcha в ASP.NET MVC и C #?

Есть несколько замечательных примеров:

  • Использование ReCaptcha с помощью ASP.NET MVC от Derik Whittaker
  • MVC reCaptcha – создание reCaptcha более MVC’ish.
  • ReCaptcha Webhelper в ASP.NET MVC 3
  • ReCaptcha Control для ASP.NET MVC из Google Code.

Это также было рассмотрено ранее в этом вопросе переполнения стека .

NuGet Google reCAPTCHA V2 для MVC 4 и 5

  • Пакет NuGet
  • Демо и документы

Я добавил reCaptcha к проекту, над которым я сейчас работаю. Мне нужно было использовать API AJAX, так как элемент reCaptcha загружался на страницу динамически. Я не мог найти никаких существующих элементов управления, и API прост, поэтому я создал свой собственный.

Я напишу свой код здесь, если кто-нибудь найдет его полезным.

1: Добавить тег скрипта в заголовки главной страницы

  

2: добавьте свои ключи в web.config

     

3: Создайте Action Attribute и расширения Html Helper

 namespace [Your chosen namespace].ReCaptcha { public enum Theme { Red, White, BlackGlass, Clean } [Serializable] public class InvalidKeyException : ApplicationException { public InvalidKeyException() { } public InvalidKeyException(string message) : base(message) { } public InvalidKeyException(string message, Exception inner) : base(message, inner) { } } public class ReCaptchaAttribute : ActionFilterAttribute { public override void OnActionExecuting(ActionExecutingContext filterContext) { var userIP = filterContext.RequestContext.HttpContext.Request.UserHostAddress; var privateKey = ConfigurationManager.AppSettings.GetString("ReCaptcha.PrivateKey", ""); if (string.IsNullOrWhiteSpace(privateKey)) throw new InvalidKeyException("ReCaptcha.PrivateKey missing from appSettings"); var postData = string.Format("&privatekey={0}&remoteip={1}&challenge={2}&response={3}", privateKey, userIP, filterContext.RequestContext.HttpContext.Request.Form["recaptcha_challenge_field"], filterContext.RequestContext.HttpContext.Request.Form["recaptcha_response_field"]); var postDataAsBytes = Encoding.UTF8.GetBytes(postData); // Create web request var request = WebRequest.Create("http://www.google.com/recaptcha/api/verify"); request.Method = "POST"; request.ContentType = "application/x-www-form-urlencoded"; request.ContentLength = postDataAsBytes.Length; var dataStream = request.GetRequestStream(); dataStream.Write(postDataAsBytes, 0, postDataAsBytes.Length); dataStream.Close(); // Get the response. var response = request.GetResponse(); using (dataStream = response.GetResponseStream()) { using (var reader = new StreamReader(dataStream)) { var responseFromServer = reader.ReadToEnd(); if (!responseFromServer.StartsWith("true")) ((Controller)filterContext.Controller).ModelState.AddModelError("ReCaptcha", "Captcha words typed incorrectly"); } } } } public static class HtmlHelperExtensions { public static MvcHtmlString GenerateCaptcha(this HtmlHelper helper, Theme theme, string callBack = null) { const string htmlInjectString = @"
"; var publicKey = ConfigurationManager.AppSettings.GetString("ReCaptcha.PublicKey", ""); if (string.IsNullOrWhiteSpace(publicKey)) throw new InvalidKeyException("ReCaptcha.PublicKey missing from appSettings"); if (!string.IsNullOrWhiteSpace(callBack)) callBack = string.Concat(", callback: ", callBack); var html = string.Format(htmlInjectString, publicKey, theme.ToString().ToLower(), callBack); return MvcHtmlString.Create(html); } } }

4: добавьте капчу к вашему виду

 @using (Html.BeginForm("MyAction", "MyController")) { @Html.TextBox("EmailAddress", Model.EmailAddress) @Html.GenerateCaptcha(Theme.White)  } 

5: добавьте атрибут к вашему действию

 [HttpPost] [ReCaptcha] public ActionResult MyAction(MyModel model) { if (!ModelState.IsValid) // Will have a Model Error "ReCaptcha" if the user input is incorrect return Json(new { capthcaInvalid = true }); ... other stuff ... } 

6: Обратите внимание, что вам нужно будет перезагрузить captcha после каждого сообщения, даже если оно было действительным, а другая часть формы была недействительной. Используйте Recaptcha.reload();

Простое и полное решение работает для меня. Поддерживает ASP.NET MVC 4 и 5 (поддерживает ASP.NET 4.0, 4.5 и 4.5.1)

Шаг 1. Установите пакет NuGet с помощью « Install-Package reCAPTCH.MVC ».

Шаг 2. Добавьте свой общеansible и закрытый ключ в файл web.config в разделе настроек приложения.

     

Вы можете создать пару ключей API для своего сайта на странице https://www.google.com/recaptcha/intro/index.html и нажать «Получить reCAPTCHA» в верхней части страницы.

Шаг 3: измените форму, чтобы включить reCaptcha

 @using reCAPTCHA.MVC @using (Html.BeginForm()) { @Html.Recaptcha() @Html.ValidationMessage("ReCaptcha")  } 

Шаг 4 : Внедрите действие controllerа, которое будет обрабатывать отправку формы и проверку Captcha

 [CaptchaValidator( PrivateKey = "your private reCaptcha Google Key", ErrorMessage = "Invalid input captcha.", RequiredMessage = "The captcha field is required.")] public ActionResult MyAction(myVM model) { if (ModelState.IsValid) //this will take care of captcha { } } 

ИЛИ

 public ActionResult MyAction(myVM model, bool captchaValid) { if (captchaValid) //manually check for captchaValid { } } 

Я успешно реализовал ReCaptcha следующим образом.
примечание: это в VB, но может быть легко преобразовано

1] Сначала возьмите копию библиотеки reCaptcha

2] Затем создайте пользовательский помощник HTML ReCaptcha

  ''# fix SO code coloring issue.  Public Function reCaptcha(ByVal htmlHelper As HtmlHelper) As MvcHtmlString Dim captchaControl = New Recaptcha.RecaptchaControl With {.ID = "recaptcha", .Theme = "clean", .PublicKey = "XXXXXX", .PrivateKey = "XXXXXX"} Dim htmlWriter = New HtmlTextWriter(New IO.StringWriter) captchaControl.RenderControl(htmlWriter) Return MvcHtmlString.Create(htmlWriter.InnerWriter.ToString) End Function 

3] Теперь вам понадобится повторный использование валидатора на стороне сервера

 Public Class ValidateCaptchaAttribute : Inherits ActionFilterAttribute Private Const CHALLENGE_FIELD_KEY As String = "recaptcha_challenge_field" Private Const RESPONSE_FIELD_KEY As String = "recaptcha_response_field" Public Overrides Sub OnActionExecuting(ByVal filterContext As ActionExecutingContext) If IsNothing(filterContext.HttpContext.Request.Form(CHALLENGE_FIELD_KEY)) Then ''# this will push the result value into a parameter in our Action filterContext.ActionParameters("CaptchaIsValid") = True Return End If Dim captchaChallengeValue = filterContext.HttpContext.Request.Form(CHALLENGE_FIELD_KEY) Dim captchaResponseValue = filterContext.HttpContext.Request.Form(RESPONSE_FIELD_KEY) Dim captchaValidtor = New RecaptchaValidator() With {.PrivateKey = "xxxxx", .RemoteIP = filterContext.HttpContext.Request.UserHostAddress, .Challenge = captchaChallengeValue, .Response = captchaResponseValue} Dim recaptchaResponse = captchaValidtor.Validate() ''# this will push the result value into a parameter in our Action filterContext.ActionParameters("CaptchaIsValid") = recaptchaResponse.IsValid MyBase.OnActionExecuting(filterContext) End Sub 

над этой строкой можно использовать многократно ** ОДИН ВРЕМЯ ** код


ниже этой строки, насколько легко реализовать reCaptcha снова и снова

Теперь, когда у вас есть код для повторного использования … все, что вам нужно сделать, это добавить капчу в свой вид.

 <%: Html.reCaptcha %> 

И когда вы отправляете форму своему controllerу …

  ''# Fix SO code coloring issues   Function Add(ByVal CaptchaIsValid As Boolean, ByVal [event] As Domain.Event) As ActionResult If Not CaptchaIsValid Then ModelState.AddModelError("recaptcha", "*") '#' Validate the ModelState and submit the data. If ModelState.IsValid Then ''# Post the form Else ''# Return View([event]) End If End Function 

Шаг 1. Интеграция сайта клиента.

Вставьте этот fragment перед закрывающим в свой HTML-шаблон:

  

Вставьте этот fragment в конце

где вы хотите, чтобы появился виджет reCAPTCHA:

 

Шаг 2: Интеграция сайтов на сервере

Когда ваши пользователи отправляют форму, в которую вы интегрировали reCAPTCHA, вы получите как часть полезной нагрузки строку с именем «g-recaptcha-response». Чтобы проверить, проверял ли Google этого пользователя, отправьте запрос POST с этими параметрами:

URL: https://www.google.com/recaptcha/api/siteverify

секрет: секретный ключ

response: Значение «g-recaptcha-response».

Теперь в действии вашего приложения MVC:

 // return ActionResult if you want public string RecaptchaWork() { // Get recaptcha value var r = Request.Params["g-recaptcha-response"]; // ... validate null or empty value if you want // then // make a request to recaptcha api using (var wc = new WebClient()) { var validateString = string.Format( "https://www.google.com/recaptcha/api/siteverify?secret={0}&response={1}", "your_secret_key", // secret recaptcha key r); // recaptcha value // Get result of recaptcha var recaptcha_result = wc.DownloadString(validateString); // Just check if request make by user or bot if (recaptcha_result.ToLower().Contains("false")) { return "recaptcha false"; } } // Do your work if request send from human :) } 

Версия async для MVC 5 (то есть, избегая ActionFilterAttribute, который не является асинхронным до MVC 6) и reCAPTCHA 2

ExampleController.cs

 public class HomeController : Controller { [HttpPost] [ValidateAntiForgeryToken] public async Task ContactSubmit( [Bind(Include = "FromName, FromEmail, FromPhone, Message, ContactId")] ContactViewModel model) { if (!await RecaptchaServices.Validate(Request)) { ModelState.AddModelError(string.Empty, "You have not confirmed that you are not a robot"); } if (ModelState.IsValid) { ... 

ExampleView.cshtml

 @model MyMvcApp.Models.ContactViewModel @*This is assuming the master layout places the styles section within the head tags*@ @section Styles { @Styles.Render("~/Content/ContactPage.css")  } @using (Html.BeginForm("ContactSubmit", "Home",FormMethod.Post, new { id = "contact-form" })) { @Html.AntiForgeryToken() ... 
@Html.LabelFor(m => m.Message) @Html.TextAreaFor(m => m.Message, new { @class = "form-control", @cols = "40", @rows = "3" }) @Html.ValidationMessageFor(m => m.Message)
}

RecaptchaServices.cs

 using System; using System.Collections.Generic; using System.Threading.Tasks; using System.Web; using System.Configuration; using System.Net.Http; using System.Net.Http.Headers; using Newtonsoft.Json; using System.Runtime.Serialization; namespace MyMvcApp.Services { public class RecaptchaServices { //ActionFilterAttribute has no async for MVC 5 therefore not using as an actionfilter attribute - needs revisiting in MVC 6 internal static async Task Validate(HttpRequestBase request) { string recaptchaResponse = request.Form["g-recaptcha-response"]; if (string.IsNullOrEmpty(recaptchaResponse)) { return false; } using (var client = new HttpClient { BaseAddress = new Uri("https://www.google.com") }) { client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); var content = new FormUrlEncodedContent(new[] { new KeyValuePair("secret", ConfigurationManager.AppSettings["RecaptchaSecret"]), new KeyValuePair("response", recaptchaResponse), new KeyValuePair("remoteip", request.UserHostAddress) }); var result = await client.PostAsync("/recaptcha/api/siteverify", content); result.EnsureSuccessStatusCode(); string jsonString = await result.Content.ReadAsStringAsync(); var response = JsonConvert.DeserializeObject(jsonString); return response.Success; } } [DataContract] internal class RecaptchaResponse { [DataMember(Name = "success")] public bool Success { get; set; } [DataMember(Name = "challenge_ts")] public DateTime ChallengeTimeStamp { get; set; } [DataMember(Name = "hostname")] public string Hostname { get; set; } [DataMember(Name = "error-codes")] public IEnumerable ErrorCodes { get; set; } } } } 

web.config

        

Для кого-то еще, смотрящего, вот достойный набор шагов. http://forums.asp.net/t/1678976.aspx/1

Не забудьте вручную добавить свой ключ в OnActionExecuting (), как я.

Расширение ответа Magpie, вот код для фильтра действий, который я использую в своем проекте.

Он работает с ASP Core RC2!

 public class ReCaptchaAttribute : ActionFilterAttribute { private readonly string CAPTCHA_URL = "https://www.google.com/recaptcha/api/siteverify"; private readonly string SECRET = "your_secret"; public override void OnActionExecuting(ActionExecutingContext filterContext) { try { // Get recaptcha value var captchaResponse = filterContext.HttpContext.Request.Form["g-recaptcha-response"]; using (var client = new HttpClient()) { var values = new Dictionary { { "secret", SECRET }, { "response", captchaResponse }, { "remoteip", filterContext.HttpContext.Request.HttpContext.Connection.RemoteIpAddress.ToString() } }; var content = new FormUrlEncodedContent(values); var result = client.PostAsync(CAPTCHA_URL, content).Result; if (result.IsSuccessStatusCode) { string responseString = result.Content.ReadAsStringAsync().Result; var captchaResult = JsonConvert.DeserializeObject(responseString); if (!captchaResult.Success) { ((Controller)filterContext.Controller).ModelState.AddModelError("ReCaptcha", "Captcha not solved"); } } else { ((Controller)filterContext.Controller).ModelState.AddModelError("ReCaptcha", "Captcha error"); } } } catch (System.Exception) { ((Controller)filterContext.Controller).ModelState.AddModelError("ReCaptcha", "Unknown error"); } } } 

И используйте его в своем коде, как

 [ReCaptcha] public IActionResult Authenticate() { if (!ModelState.IsValid) { return View( "Login", new ReturnUrlViewModel { ReturnUrl = Request.Query["returnurl"], IsError = true, Error = "Wrong reCAPTCHA" } ); } 
  • переменная условия - почему вызов pthread_cond_signal () перед вызовом pthread_cond_wait () является логической ошибкой?
  • Вызов библиотеки C ++ в C #
  • unsigned int и подписанное сравнение символов
  • Изменено ли использование foreach переменных в C # 5?
  • Как написать в середине файла в C ++?
  • Какие исключения я не должен улавливать?
  • Как мне войти на сайт с помощью WebClient?
  • ASP.NET Core MVC: как получить необработанный JSON привязан к строке без типа?
  • Инициализация статических переменных в C
  • Выбросить HttpResponseException или вернуть Request.CreateErrorResponse?
  • Как поймать ВСЕ исключения / сбои в приложении .NET
  • Давайте будем гением компьютера.