8 ответов:
есть несколько замечательных примеров:
- используя ReCaptcha с ASP.NET MVC Дерик Уиттакер
- MVC reCaptcha - делая reCaptcha больше MVC'ish.
- ReCaptcha Webhelper in ASP.NET MVC 3
- управление ReCaptcha для ASP.NET MVC из кода Google.
Это также было рассмотрено ранее в это переполнение стека вопрос.
NuGet Google reCAPTCHA V2 для MVC 4 и 5
я добавил reCaptcha к проекту, над которым я сейчас работаю. Мне нужно было использовать AJAX API, поскольку элемент reCaptcha был загружен на страницу динамически. Я не мог найти никаких существующих элементов управления, и API прост, поэтому я создал свой собственный.
я опубликую свой код здесь, Если кто-нибудь найдет его полезным.
1: добавьте тег script в заголовки главной страницы
<script type="text/javascript" src="http://www.google.com/recaptcha/api/js/recaptcha_ajax.js"></script>2: Добавьте ваши ключи к сеть.конфигурации
<appSettings> <add key="ReCaptcha.PrivateKey" value="[key here]" /> <add key="ReCaptcha.PublicKey" value="[key here]" /> </appSettings>3: Создайте атрибут действия и вспомогательные расширения Html
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 = @"<div id=""recaptcha_div""></div> <script type=""text/javascript""> Recaptcha.create(""{0}"", ""recaptcha_div"", {{ theme: ""{1}"" {2}}}); </script>"; 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) <input type="submit" value="Submit" /> }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: Примечание вам нужно будет перезагрузить капчу после каждого сообщения, даже если оно было действительным, а другая часть формы была недействительной. Используйте
Recaptcha.reload();
простое и полное решение работает для меня. Опоры ASP.NET MVC 4 и 5 (Поддержка ASP.NET 4.0, 4.5 и 4.5.1)
Шаг 1: установите пакет NuGet с помощью "Install-Package reCAPTCH.MVC"
Шаг 2: Добавить свой открытый и закрытый ключ к вашей сети.файл config в разделе appsettings
<appSettings> <add key="ReCaptchaPrivateKey" value=" -- PRIVATE_KEY -- " /> <add key="ReCaptchaPublicKey" value=" -- PUBLIC KEY -- " /> </appSettings>вы можете создать пару ключей API для вашего сайта по https://www.google.com/recaptcha/intro/index.html и нажмите на Получить reCAPTCHA в верхней части страницы
Шаг 3: измените свою форму, чтобы включить reCaptcha
@using reCAPTCHA.MVC @using (Html.BeginForm()) { @Html.Recaptcha() @Html.ValidationMessage("ReCaptcha") <input type="submit" value="Register" /> }Шаг 4: реализовать действие контроллера, который будет обрабатывать форму представления и проверки 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] Сначала возьмите копию рекапчи библиотека
2] затем создайте пользовательский помощник ReCaptcha HTML
''# fix SO code coloring issue. <Extension()> 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 Function3] отсюда вам нужен многоразовый валидатор на стороне сервера
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 %>и когда вы отправляете форму на ваш контроллер...
''# Fix SO code coloring issues <ValidateCaptcha()> <AcceptVerbs(HttpVerbs.Post)> 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: интеграция сайта клиента
вставьте этот фрагмент перед закрытием
</head>тег на вашем HTML шаблоне:<script src='https://www.google.com/recaptcha/api.js'></script>вставьте этот фрагмент в конце
<form>где вы хотите, чтобы виджет reCAPTCHA появился:<div class="g-recaptcha" data-sitekey="your-site-key"></div>Шаг 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 :) }
асинхронная версия для MVC 5 (т. е. избегая ActionFilterAttribute, который не является асинхронным до MVC 6) и reCAPTCHA 2
ExampleController.cs
public class HomeController : Controller { [HttpPost] [ValidateAntiForgeryToken] public async Task<ActionResult> 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") <script src='https://www.google.com/recaptcha/api.js'></script> } @using (Html.BeginForm("ContactSubmit", "Home",FormMethod.Post, new { id = "contact-form" })) { @Html.AntiForgeryToken() ... <div class="form-group"> @Html.LabelFor(m => m.Message) @Html.TextAreaFor(m => m.Message, new { @class = "form-control", @cols = "40", @rows = "3" }) @Html.ValidationMessageFor(m => m.Message) </div> <div class="row"> <div class="g-recaptcha" data-sitekey='@System.Configuration.ConfigurationManager.AppSettings["RecaptchaClientKey"]'></div> </div> <div class="row"> <input type="submit" id="submit-button" class="btn btn-default" value="Send Your Message" /> </div> }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<bool> 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<string, string>("secret", ConfigurationManager.AppSettings["RecaptchaSecret"]), new KeyValuePair<string, string>("response", recaptchaResponse), new KeyValuePair<string, string>("remoteip", request.UserHostAddress) }); var result = await client.PostAsync("/recaptcha/api/siteverify", content); result.EnsureSuccessStatusCode(); string jsonString = await result.Content.ReadAsStringAsync(); var response = JsonConvert.DeserializeObject<RecaptchaResponse>(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<string> ErrorCodes { get; set; } } } }web.конфигурации
<configuration> <appSettings> <!--recaptcha--> <add key="RecaptchaSecret" value="***secret key from https://developers.google.com/recaptcha***" /> <add key="RecaptchaClientKey" value="***client key from https://developers.google.com/recaptcha***" /> </appSettings> </configuration>
для тех, кто еще ищет, вот приличный набор шагов. http://forums.asp.net/t/1678976.aspx/1
Не забудьте вручную добавить свой ключ в OnActionExecuting (), как я сделал.
расширяя ответ Сороки, вот код фильтра действий, который я использую в своем проекте.
Он работает с 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<string, string> { { "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<CaptchaResponseViewModel>(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" } ); }
Comments