Làm thế nào để triển khai reCaptcha cho ASP.NET MVC? [đóng cửa]


80

Làm cách nào để triển khai reCaptcha trong ASP.NET MVC và C #?


Nếu bạn đang tìm giải pháp mới nhất của Kết hợp Google reCAPTCHA v2 & v3 trong Biểu mẫu web ASP.NET, hãy xem bản demo techtolia.com/Recaptcha
Leo

Câu trả lời:


83

Có một vài ví dụ tuyệt vời:

Điều này cũng đã được đề cập trước đây trong câu hỏi Stack Overflow này .

NuGet Google reCAPTCHA V2 cho MVC 4 và 5


cảm ơn vì đã trả lời nhanh chóng. Tôi có một câu hỏi, ai đã tạo ra Recaptcha.dll? Nhóm Google?
xport

4
Tôi tin rằng ReCaptcha được tạo ra bởi một giáo sư tại Đại học Carnegie Mellon .
George Stocker

1
Cái thứ ba ( dotnetcurry.com/ShowArticle.aspx?ID=611 ) rất hiệu quả đối với tôi.
hiếm hoi

Tôi đang sử dụng mã của Dirik Whittaker. Microsoft.Web.Helpers được tham chiếu, nhưng tôi nhận được lỗi không tìm thấy tên không gian tên 'Recaptcha' trên dòng này: var captchaValidtor = new Recaptcha.RecaptchaValidator
M3NTA7

@ M3NTA7 Bạn có thể muốn đặt một câu hỏi đi sâu hơn một chút so với nhận xét này.
George Stocker

32

Tôi đã thêm reCaptcha vào một dự án mà tôi hiện đang thực hiện. Tôi cần nó để sử dụng AJAX API vì phần tử reCaptcha được tải động vào trang. Tôi không thể tìm thấy bất kỳ điều khiển hiện có nào và API rất đơn giản nên tôi đã tạo của riêng mình.

Tôi sẽ đăng mã của mình ở đây trong trường hợp có ai thấy nó hữu ích.

1: Thêm thẻ script vào tiêu đề trang chính

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

2: Thêm khóa của bạn vào web.config

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

3: Tạo phần mở rộng Thuộc tính hành động và Trình trợ giúp 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: Thêm hình ảnh xác thực vào chế độ xem của bạn

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

5: Thêm thuộc tính vào hành động của bạn

[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: Lưu ý rằng bạn sẽ cần tải lại hình ảnh xác thực sau mỗi bài đăng ngay cả khi nó hợp lệ và một phần khác của biểu mẫu không hợp lệ. Sử dụngRecaptcha.reload();


Có thể với mã này để chỉ chú thích ReCaptcha sau 5 lần đăng nhập không thành công không?
Rob

2
Nếu bạn đang triển khai giải pháp này, hãy tính đến url API mới là: google.com/recaptcha/api/siteverify ( nguồn )
Axel Prieto

13

Giải pháp đơn giản và hoàn chỉnh phù hợp với tôi. Hỗ trợ ASP.NET MVC 4 và 5 (Hỗ trợ ASP.NET 4.0, 4.5 và 4.5.1)

Bước 1: Cài đặt Gói NuGet bằng " Install-Package reCAPTCH.MVC "

Bước 2: Thêm khóa Công khai và Riêng tư vào tệp web.config của bạn trong phần cài đặt ứng dụng

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

Bạn có thể tạo một cặp khóa API cho trang web của mình tại https://www.google.com/recaptcha/intro/index.html và nhấp vào Nhận reCAPTCHA ở đầu trang

Bước 3: Sửa đổi biểu mẫu của bạn để bao gồm reCaptcha

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

Bước 4 : Triển khai Hành động kiểm soát sẽ xử lý việc gửi biểu mẫu và xác thực 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
    {
    }
}

HOẶC LÀ

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

Rất tiếc, không thể sử dụng nó ở hai dạng khác nhau trong cùng một trang do Uncaught Error: ReCAPTCHA placeholder element must be empty.
Alisson

1
Vì reCaptcha sử dụng web.config cho các khóa nên bạn không cần cung cấp PrivateKey = "your private reCaptcha Google Key". Điều này dễ dàng hơn nhiều khi bạn có các phím khác nhau cho các môi trường khác nhau
Red

13

Phiên bản không đồng bộ cho MVC 5 (tức là tránh ActionFilterAttribute, không đồng bộ cho đến MVC 6) và 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.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>

Điều này đã làm việc cho tôi! ... MVC v5, recaptcha v2 ~ 2018
MTAdmin

8

Bước 1: Tích hợp trang web khách hàng

Dán đoạn mã này trước </head>thẻ đóng trên mẫu HTML của bạn:

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

Dán đoạn mã này vào cuối <form>nơi bạn muốn tiện ích reCAPTCHA xuất hiện:

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

Bước 2: Tích hợp trang web máy chủ

Khi người dùng của bạn gửi biểu mẫu mà bạn đã tích hợp reCAPTCHA, bạn sẽ nhận được như một phần của tải trọng một chuỗi có tên "g-recaptcha-response". Để kiểm tra xem Google đã xác minh người dùng đó chưa, hãy gửi yêu cầu ĐĂNG với các thông số sau:

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

bí mật: khóa bí mật của bạn

response: Giá trị của 'g-recaptcha-response'.

Ứng dụng MVC của bạn hiện đang hoạt động:

// 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 :)
    }

7

Tôi đã triển khai thành công ReCaptcha theo cách sau.
lưu ý: đây là trong VB, nhưng có thể dễ dàng chuyển đổi

1] Đầu tiên lấy một bản sao của thư viện reCaptcha

2] Sau đó, tạo Trình trợ giúp ReCaptcha HTML tùy chỉnh

    ''# 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] Từ đây, bạn cần trình xác thực phía máy chủ có thể sử dụng lại

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

phía trên dòng này có thể sử dụng lại ** ONE TIME ** mã


bên dưới dòng này là cách dễ dàng triển khai reCaptcha lặp đi lặp lại

Bây giờ bạn đã có mã có thể sử dụng lại ... tất cả những gì bạn cần làm là thêm hình ảnh xác thực vào Chế độ xem của bạn.

<%: Html.reCaptcha %>

Và khi bạn đăng biểu mẫu lên bộ điều khiển của mình ...

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

lưu ý: đây là trong VB nhưng có thể dễ dàng được chuyển đổi sang C #
Chase Florell

1
cảm ơn bạn rất nhiều vì đã xây dựng giải pháp. Đó là câu trả lời rất chi tiết. Tôi thích nó.
xport

1
Theo blog gần đây nhất của Joel, những người tạo ra StackOverflow muốn đây là một Kho lưu trữ Wiki thay vì chỉ chuyển hướng người dùng đến các trang web khác. Việc đưa bạn đến một trang web có thể trả lời câu hỏi của bạn ngay hôm nay, nhưng sẽ không giải quyết được vấn đề của người khác khi trang bên ngoài đó ngừng hoạt động vào năm sau. Đăng câu trả lời đúng ở đây cũng sẽ giúp ích cho những người tìm kiếm trong tương lai. Tôi tin rằng đây là cách đúng để trả lời một câu hỏi.
Chase Florell

Trông gần giống với devlicio.us/blogs/derik_whittaker/archive/2008/12/02/… ngoại trừ sự khác biệt về ngôn ngữ ..
gmail user

2

Mở rộng câu trả lời của Magpie, đây là mã cho bộ lọc hành động mà tôi sử dụng trong dự án của mình.

Nó hoạt động với 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");
        }
    }
}

Và sử dụng nó trong mã của bạn như

[ReCaptcha]
    public IActionResult Authenticate()
    {

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

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.