Использование reCAPTCHA с ASP.NET MVC

Я много раз использовал reCAPTCHA в своих приложениях WebForms. Теперь я хотел бы добавить его в приложение ASP.NET MVC.

Я нашел хороший код в RecaptchaControlMvc, но, что невероятно, я не смог найти ни одного абзаца или примера того, как использовать этот элемент управления.

Я разместил сообщение в группе Google reCAPTCHA, но она мертва.

Может ли кто-нибудь указать мне пример, в котором используется этот элемент управления, абзац о том, как его использовать, или предложить альтернативу?

Примечание. Я знаю, что в stackoverflow есть похожие вопросы, но ни один из них не обсуждал, как использовать этот элемент управления.


person Jonathan Wood    schedule 26.07.2013    source источник
comment
NuGet Google reCAPTCHA V2 для MVC 4 и 5 — пакет NuGet – Демонстрация и документ   -  person Sender    schedule 08.08.2015


Ответы (3)


Некоторый код здесь

Вы добавляете атрибут следующим образом:

[CaptchaValidator]  
[AcceptVerbs( HttpVerbs.Post )]  
public ActionResult SubmitForm( Int32 id, bool captchaValid )  
{  
.. Do something here  
}  

Вы визуализируете капчу в своем представлении:

<%= Html.GenerateCaptcha() %> 

что-то вроде этого:

public static string GenerateCaptcha( this HtmlHelper helper )  
{           
    var captchaControl = new Recaptcha.RecaptchaControl  
            {  
                    ID = "recaptcha",  
                    Theme = "blackglass",  
                PublicKey = -- Put Public Key Here --,  
                        PrivateKey = -- Put Private Key Here --  
            };  

    var htmlWriter = new HtmlTextWriter( new StringWriter() );  
    captchaControl.RenderControl(htmlWriter);  
    return htmlWriter.InnerWriter.ToString();  
}  
person Nick    schedule 26.07.2013
comment
Интересно. Я работаю над тем, чтобы капча отображалась в моем представлении с помощью @Html.GenerateCaptcha() (я использую синтаксис Razor), и она отображает разметку, а не капчу??? - person Jonathan Wood; 26.07.2013
comment
В зависимости от вашей версии MVC это может быть ‹%= Html.GenerateCaptcha() %› или @Html.GenerateCaptcha() - person Nick; 31.10.2013
comment
@JonathanWood Вы когда-нибудь заставляли его отображать фактический виджет, а не разметку? Это именно та проблема, с которой я сталкиваюсь сейчас. В документации говорится, что нужно просто вызвать GeneratreCaptcha(), но, похоже, мне нужно выполнить реальную функциональность для этого помощника? - person Adrian; 30.01.2014
comment
Неважно, вам нужно использовать @Html.Raw(Html.GenerateCaptcha()), а не просто @Html.GenerateCaptcha() - person Adrian; 30.01.2014

Вот как я это делаю с ASP.Net MVC и ReCaptcha 3.

  1. В Visual Studio 2015 или 2017 создайте новый проект ASP.NET MVC и задайте для целевой платформы .NET Framework значение 4.6.2.
  2. Создайте описательное имя для своего проекта ASP.NET MVC (например, ASPNetMVCWithReCaptcha3).
  3. Создайте свое приложение и убедитесь, что оно компилируется и не содержит ошибок.
  4. В Web.Config создайте два новых ключа и скопируйте/вставьте ключ сайта и секретный ключ из текстового редактора, в котором вы сохранили эти ссылки.
<appSettings>
    <add key="reCaptchaSiteKey" value="site_key" />
    <add key="reCaptchaSecretKey" value="secret_key" />
</appSettings>
  1. В папке «Models» создайте новый класс «ReCaptchaForm.cs» и скопируйте/вставьте следующие строки кода.
namespace ASPNetMVCWithReCaptcha3.Models
{
    public class ReCaptchaForm
    {
        public string Message { get; set; }
    }
}
  1. Создайте новую папку «Классы» в проекте.
  2. В папке «Классы» создайте новый класс «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
{
}
  1. Добавьте следующие строки внутри пространства имен

    • Add a class "GoogleReCaptchaVariables" that will store variables needed to render 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>
}
  1. Соберите проект и убедитесь, что он не содержит ошибок. В результате форма должна быть отправлена, если ReCaptcha API возвращает успешный ответ. Напротив, сообщение об ошибке будет отображаться в нижней части ввода сообщения, если API вернул неудачный ответ.
person DMObjects    schedule 16.06.2019

Я могу предоставить вам простой альтернативный метод использования google recaptcha. Здесь вы можете найти полную справку о новой reCAPTCHA Google. с помощью asp.net mvc

Прежде всего, вам нужно зарегистрироваться и создать Google reCAPTCHA API. Перейдите на страницу http://www.google.com/recaptcha, затем нажмите кнопку "Получить reCAPTCHA" в правом верхнем углу.

Во-вторых, напишите HTML-код в своем представлении. Здесь замените текст "Ваш ключ сайта"

@{
    ViewBag.Title = "Index";
}
<h2>Index</h2>
<div>
    @using (Html.BeginForm("FormSubmit", "Home", FormMethod.Post))
{
    <div class="g-recaptcha" data-sitekey="Your sitekey here"></div>
    <input type="submit" value="Submit" />
}
</div>
<span style="display:inline-block; font-size:20px;margin:20px 0;padding:20px;border:1px solid #D3D3D3">
    @ViewBag.Message
</span>
<script src='https://www.google.com/recaptcha/api.js' type="text/javascript"></script>

3-й и последний, напишите код действия для проверки google reCaptcha

[HttpPost]
public ActionResult FormSubmit()
{
    //Validate Google recaptcha here
    var response = Request["g-recaptcha-response"];
    string secretKey = "Your secret here";
    var client = new WebClient();
    var result = client.DownloadString(string.Format("https://www.google.com/recaptcha/api/siteverify?secret={0}&response={1}", secretKey, response));
    var obj = JObject.Parse(result);
    var status = (bool)obj.SelectToken("success");
    ViewBag.Message = status ? "Google reCaptcha validation success" : "Google reCaptcha validation failed";

    //When you will post form for save data, you should check both the model validation and google recaptcha validation
    //EX.
    /* if (ModelState.IsValid && status)
    {

    }*/

    //Here I am returning to Index page for demo perpose, you can use your view here
    return View("Index");
}
person Sourav Mondal    schedule 16.12.2015