如何实现ASP的reCaptcha。净MVC吗?

时间:2022-10-15 14:30:56

How do I implement reCaptcha in ASP.NET MVC and C#?

如何在ASP中实现reCaptcha。净MVC和c#吗?

8 个解决方案

#1


71  

There are a few great examples:

有几个很好的例子:

This has also been covered before in this Stack Overflow question.

在这个堆栈溢出问题中也讨论过这个问题。

NuGet Google reCAPTCHA V2 for MVC 4 and 5

NuGet谷歌重新验证了MVC 4和5的V2

#2


27  

I have added reCaptcha to a project I'm currently working on. I needed it to use the AJAX API as the reCaptcha element was loaded into the page dynamically. I couldn't find any existing controls and the API is simple so I created my own.

我已经在我正在开发的项目中添加了reCaptcha。我需要它来使用AJAX API,因为它是动态加载到页面中的。我找不到任何现有的控件,API也很简单,所以我创建了自己的控件。

I'll post my code here in case anyone finds it useful.

我将把我的代码放在这里,以防有人发现它有用。

1: Add the script tag to the master page headers

1:将脚本标记添加到主页头

<script type="text/javascript" src="http://www.google.com/recaptcha/api/js/recaptcha_ajax.js"></script>

2: Add your keys to the web.config

2:在web.config中添加你的键

<appSettings>
    <add key="ReCaptcha.PrivateKey" value="[key here]" />
    <add key="ReCaptcha.PublicKey" value="[key here]" />
</appSettings>

3: Create the Action Attribute and Html Helper extensions

3:创建Action属性和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 = @"<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: Add the captcha to your view

4:将验证码添加到视图中

@using (Html.BeginForm("MyAction", "MyController"))
{
   @Html.TextBox("EmailAddress", Model.EmailAddress)
   @Html.GenerateCaptcha(Theme.White)
   <input type="submit" value="Submit" />
}

5: Add the attribute to your action

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: Note you will need to reload the captcha after each post even if it was valid and another part of the form was invalid. Use Recaptcha.reload();

6:注意,你需要在每个帖子之后重新加载验证码,即使它是有效的并且表单的另一部分是无效的。使用Recaptcha.reload();

#3


7  

Simple and Complete Solution working for me. Supports ASP.NET MVC 4 and 5 (Supports ASP.NET 4.0, 4.5, and 4.5.1)

简单而完整的解决方案对我有效。支持ASP。NET MVC 4和5(支持ASP。NET 4.0、4.5和4.5.1)

Step 1: Install NuGet Package by "Install-Package reCAPTCH.MVC"

步骤1:通过“Install-Package reCAPTCH.MVC”安装NuGet包

Step 2: Add your Public and Private key to your web.config file in appsettings section

步骤2:将您的公钥和私钥添加到web中。配置文件在appsettings部分

<appSettings>
    <add key="ReCaptchaPrivateKey" value=" -- PRIVATE_KEY -- " />
    <add key="ReCaptchaPublicKey" value=" -- PUBLIC KEY -- " />
</appSettings>  

You can create an API key pair for your site at https://www.google.com/recaptcha/intro/index.html and click on Get reCAPTCHA at top of the page

您可以在https://www.google.com/recaptcha/intro/index.html为您的站点创建一个API密钥对,然后单击页面顶部的Get reCAPTCHA

Step 3: Modify your form to include reCaptcha

步骤3:修改表单以包含reCaptcha。

@using reCAPTCHA.MVC
@using (Html.BeginForm())
{
    @Html.Recaptcha()
    @Html.ValidationMessage("ReCaptcha")
    <input type="submit" value="Register" />
}

Step 4: Implement the Controller Action that will handle the form submission and Captcha validation

步骤4:实现控制器操作,该操作将处理表单提交和验证码验证

[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
    {
    }
}

OR

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

#4


6  

I've successfully implemented ReCaptcha in the following way.
note: this is in VB, but can easily be converted

我以以下方式成功地实现了ReCaptcha。注意:这是在VB中,但是可以很容易地转换

1] First grab a copy of the reCaptcha library

首先抓取一个reCaptcha库的副本

2] Then build a custom ReCaptcha HTML Helper

然后,构建一个自定义的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 Function

3] From here you need a re-usable server side validator

从这里您需要一个可重复使用的服务器端验证器。

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

above this line is reusable **ONE TIME** code


below this line is how easy it is to implement reCaptcha over and over

Now that you have your re-usable code... all you need to do is add the captcha to your View.

现在您有了可重用的代码……您所需要做的就是将captcha添加到您的视图中。

<%: Html.reCaptcha %>

And when you post the form to your controller...

当你把表单提交给你的控制器时…

    ''# 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

#5


5  

Step 1: Client site integration

步骤1:客户端站点集成

Paste this snippet before the closing </head> tag on your HTML template:

在HTML模板上的结束标签之前粘贴这个代码片段:

<script src='https://www.google.com/recaptcha/api.js'></script>

Paste this snippet at the end of the <form> where you want the reCAPTCHA widget to appear:

将此代码片段粘贴到

的末尾,您希望reCAPTCHA小部件出现:

<div class="g-recaptcha" data-sitekey="your-site-key"></div>

Step 2: Server site integration

步骤2:服务器站点集成

When your users submit the form where you integrated reCAPTCHA, you'll get as part of the payload a string with the name "g-recaptcha-response". In order to check whether Google has verified that user, send a POST request with these parameters:

当用户提交集成了reCAPTCHA的表单时,将获得一个名为“g-recaptcha-response”的字符串作为有效负载的一部分。为了检查谷歌是否验证了该用户,发送带有以下参数的POST请求:

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

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

secret : your secret key

秘密:你的秘密钥匙

response : The value of 'g-recaptcha-response'.

响应:“g-recaptcha-response”的值。

Now in action of your MVC app:

现在你的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 :)
    }

#6


4  

An async version for MVC 5 (i.e. avoiding ActionFilterAttribute, which is not async until MVC 6) and reCAPTCHA 2

MVC 5的异步版本(例如避免ActionFilterAttribute,这在MVC 6之前是不异步的)和reCAPTCHA 2

ExampleController.cs

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

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

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.config

. config

<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>

#7


1  

For anybody else looking, here is a decent set of steps. http://forums.asp.net/t/1678976.aspx/1

对于其他人来说,这里有一组不错的步骤。http://forums.asp.net/t/1678976.aspx/1

Don't forget to manually add your key in OnActionExecuting() like I did.

不要忘记像我一样在onactionexecution()中手动添加密钥。

#8


1  

Extending Magpie's answer, here is the code for action filter which I use in my project.

扩展Magpie的答案,这里是我在项目中使用的动作过滤器代码。

It works with ASP Core RC2!

它与ASP核心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");
        }
    }
}

And use it in your code like

在代码中使用它

[ReCaptcha]
    public IActionResult Authenticate()
    {

        if (!ModelState.IsValid)
        {
            return View(
                "Login",
                new ReturnUrlViewModel
                {
                    ReturnUrl = Request.Query["returnurl"],
                    IsError = true,
                    Error = "Wrong reCAPTCHA"
                }
            );
        }

#1


71  

There are a few great examples:

有几个很好的例子:

This has also been covered before in this Stack Overflow question.

在这个堆栈溢出问题中也讨论过这个问题。

NuGet Google reCAPTCHA V2 for MVC 4 and 5

NuGet谷歌重新验证了MVC 4和5的V2

#2


27  

I have added reCaptcha to a project I'm currently working on. I needed it to use the AJAX API as the reCaptcha element was loaded into the page dynamically. I couldn't find any existing controls and the API is simple so I created my own.

我已经在我正在开发的项目中添加了reCaptcha。我需要它来使用AJAX API,因为它是动态加载到页面中的。我找不到任何现有的控件,API也很简单,所以我创建了自己的控件。

I'll post my code here in case anyone finds it useful.

我将把我的代码放在这里,以防有人发现它有用。

1: Add the script tag to the master page headers

1:将脚本标记添加到主页头

<script type="text/javascript" src="http://www.google.com/recaptcha/api/js/recaptcha_ajax.js"></script>

2: Add your keys to the web.config

2:在web.config中添加你的键

<appSettings>
    <add key="ReCaptcha.PrivateKey" value="[key here]" />
    <add key="ReCaptcha.PublicKey" value="[key here]" />
</appSettings>

3: Create the Action Attribute and Html Helper extensions

3:创建Action属性和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 = @"<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: Add the captcha to your view

4:将验证码添加到视图中

@using (Html.BeginForm("MyAction", "MyController"))
{
   @Html.TextBox("EmailAddress", Model.EmailAddress)
   @Html.GenerateCaptcha(Theme.White)
   <input type="submit" value="Submit" />
}

5: Add the attribute to your action

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: Note you will need to reload the captcha after each post even if it was valid and another part of the form was invalid. Use Recaptcha.reload();

6:注意,你需要在每个帖子之后重新加载验证码,即使它是有效的并且表单的另一部分是无效的。使用Recaptcha.reload();

#3


7  

Simple and Complete Solution working for me. Supports ASP.NET MVC 4 and 5 (Supports ASP.NET 4.0, 4.5, and 4.5.1)

简单而完整的解决方案对我有效。支持ASP。NET MVC 4和5(支持ASP。NET 4.0、4.5和4.5.1)

Step 1: Install NuGet Package by "Install-Package reCAPTCH.MVC"

步骤1:通过“Install-Package reCAPTCH.MVC”安装NuGet包

Step 2: Add your Public and Private key to your web.config file in appsettings section

步骤2:将您的公钥和私钥添加到web中。配置文件在appsettings部分

<appSettings>
    <add key="ReCaptchaPrivateKey" value=" -- PRIVATE_KEY -- " />
    <add key="ReCaptchaPublicKey" value=" -- PUBLIC KEY -- " />
</appSettings>  

You can create an API key pair for your site at https://www.google.com/recaptcha/intro/index.html and click on Get reCAPTCHA at top of the page

您可以在https://www.google.com/recaptcha/intro/index.html为您的站点创建一个API密钥对,然后单击页面顶部的Get reCAPTCHA

Step 3: Modify your form to include reCaptcha

步骤3:修改表单以包含reCaptcha。

@using reCAPTCHA.MVC
@using (Html.BeginForm())
{
    @Html.Recaptcha()
    @Html.ValidationMessage("ReCaptcha")
    <input type="submit" value="Register" />
}

Step 4: Implement the Controller Action that will handle the form submission and Captcha validation

步骤4:实现控制器操作,该操作将处理表单提交和验证码验证

[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
    {
    }
}

OR

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

#4


6  

I've successfully implemented ReCaptcha in the following way.
note: this is in VB, but can easily be converted

我以以下方式成功地实现了ReCaptcha。注意:这是在VB中,但是可以很容易地转换

1] First grab a copy of the reCaptcha library

首先抓取一个reCaptcha库的副本

2] Then build a custom ReCaptcha HTML Helper

然后,构建一个自定义的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 Function

3] From here you need a re-usable server side validator

从这里您需要一个可重复使用的服务器端验证器。

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

above this line is reusable **ONE TIME** code


below this line is how easy it is to implement reCaptcha over and over

Now that you have your re-usable code... all you need to do is add the captcha to your View.

现在您有了可重用的代码……您所需要做的就是将captcha添加到您的视图中。

<%: Html.reCaptcha %>

And when you post the form to your controller...

当你把表单提交给你的控制器时…

    ''# 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

#5


5  

Step 1: Client site integration

步骤1:客户端站点集成

Paste this snippet before the closing </head> tag on your HTML template:

在HTML模板上的结束标签之前粘贴这个代码片段:

<script src='https://www.google.com/recaptcha/api.js'></script>

Paste this snippet at the end of the <form> where you want the reCAPTCHA widget to appear:

将此代码片段粘贴到

的末尾,您希望reCAPTCHA小部件出现:

<div class="g-recaptcha" data-sitekey="your-site-key"></div>

Step 2: Server site integration

步骤2:服务器站点集成

When your users submit the form where you integrated reCAPTCHA, you'll get as part of the payload a string with the name "g-recaptcha-response". In order to check whether Google has verified that user, send a POST request with these parameters:

当用户提交集成了reCAPTCHA的表单时,将获得一个名为“g-recaptcha-response”的字符串作为有效负载的一部分。为了检查谷歌是否验证了该用户,发送带有以下参数的POST请求:

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

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

secret : your secret key

秘密:你的秘密钥匙

response : The value of 'g-recaptcha-response'.

响应:“g-recaptcha-response”的值。

Now in action of your MVC app:

现在你的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 :)
    }

#6


4  

An async version for MVC 5 (i.e. avoiding ActionFilterAttribute, which is not async until MVC 6) and reCAPTCHA 2

MVC 5的异步版本(例如避免ActionFilterAttribute,这在MVC 6之前是不异步的)和reCAPTCHA 2

ExampleController.cs

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

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

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.config

. config

<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>

#7


1  

For anybody else looking, here is a decent set of steps. http://forums.asp.net/t/1678976.aspx/1

对于其他人来说,这里有一组不错的步骤。http://forums.asp.net/t/1678976.aspx/1

Don't forget to manually add your key in OnActionExecuting() like I did.

不要忘记像我一样在onactionexecution()中手动添加密钥。

#8


1  

Extending Magpie's answer, here is the code for action filter which I use in my project.

扩展Magpie的答案,这里是我在项目中使用的动作过滤器代码。

It works with ASP Core RC2!

它与ASP核心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");
        }
    }
}

And use it in your code like

在代码中使用它

[ReCaptcha]
    public IActionResult Authenticate()
    {

        if (!ModelState.IsValid)
        {
            return View(
                "Login",
                new ReturnUrlViewModel
                {
                    ReturnUrl = Request.Query["returnurl"],
                    IsError = true,
                    Error = "Wrong reCAPTCHA"
                }
            );
        }