ASP.NET MVC용 reCaptcha를 구현하는 방법은 무엇입니까?
ASP.NET MVC 및 C#에서 reCaptcha를 구현하려면 어떻게 해야 합니까?
몇 가지 훌륭한 예가 있습니다.
- MVC reCaptcha - reCaptcha를 더 MVC'ish로 만듭니다.
- ASP.NET MVC의 웹 도우미 재캡처 3
- Google 코드에서 ASP.NET MVC에 대한 제어를 다시 캡처합니다.
이 문제는 이전에 이 스택 오버플로 질문에서도 다루었습니다.
MVC 4 및 5용 NuGet Google reCAPTCHA V2
현재 진행 중인 프로젝트에 reCaptcha를 추가했습니다.reCaptcha 요소가 페이지에 동적으로 로드되어 AJAX API를 사용하기 위해 필요했습니다.기존 컨트롤을 찾을 수 없었고 API가 간단해서 직접 만들었습니다.
누군가 유용하다고 생각될 경우를 대비해 제 코드를 여기에 올리겠습니다.
1: 마스터 페이지 헤더에 스크립트 태그 추가
<script type="text/javascript" src="http://www.google.com/recaptcha/api/js/recaptcha_ajax.js"></script>
2: web.config에 키를 추가합니다.
<appSettings>
<add key="ReCaptcha.PrivateKey" value="[key here]" />
<add key="ReCaptcha.PublicKey" value="[key here]" />
</appSettings>
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 = @"<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단계: "Install-Package reCAPTCH.MVC"를 통해 NuGet 패키지를 설치합니다.
2단계: 앱 설정 섹션의 web.config 파일에 공용 및 개인 키 추가
<appSettings>
<add key="ReCaptchaPrivateKey" value=" -- PRIVATE_KEY -- " />
<add key="ReCaptchaPublicKey" value=" -- PUBLIC KEY -- " />
</appSettings>
https://www.google.com/recaptcha/intro/index.html 에서 사이트에 대한 API 키 쌍을 생성하고 페이지 상단에서 Get reCAPTCHA를 클릭할 수 있습니다.
3단계: reCaptcha를 포함하도록 양식 수정
@using reCAPTCHA.MVC
@using (Html.BeginForm())
{
@Html.Recaptcha()
@Html.ValidationMessage("ReCaptcha")
<input type="submit" value="Register" />
}
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
{
}
}
MVC 5(즉, MVC 6까지 비동기가 아닌 ActionFilterAttribute 회피) 및 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)
{
...
예제View.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>
1단계: 클라이언트 사이트 통합
" 기전이스붙을여펫다니습넣니닫에▁the다▁this▁paste" 앞에 붙여주세요.</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-recapcha-response"라는 이름의 문자열이 페이로드의 일부로 제공됩니다.Google에서 해당 사용자를 확인했는지 확인하려면 다음 매개 변수를 사용하여 POST 요청을 전송합니다.
URL : https://www.google.com/recaptcha/api/siteverify
secret : 당신의 비밀키
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 :)
}
저는 다음과 같은 방법으로 ReCaptcha를 성공적으로 구현했습니다.
되어 할 수 있습니다.
먼저 reCaptcha 라이브러리의 복사본을 가져옵니다.
그런 다음 사용자 지정 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
여기서 재사용 가능한 서버 측 검증기가 필요합니다.
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
이 줄 위에는 재사용 가능한 **ONE TIME** 코드가 있습니다.
이 선 아래는 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
까치의 답변을 확장하여, 여기 제 프로젝트에서 사용하는 액션 필터의 코드가 있습니다.
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"
}
);
}
다른 사람들을 위해, 여기 괜찮은 단계들이 있습니다.http://forums.asp.net/t/1678976.aspx/1
OnAction에서 키를 수동으로 추가하는 것을 잊지 마십시오.나처럼 ()을 실행하는 것.
언급URL : https://stackoverflow.com/questions/4611122/how-to-implement-recaptcha-for-asp-net-mvc
'code' 카테고리의 다른 글
XML 구성 파일에서 Spring Boot 자동 구성 빈을 사용하려면 어떻게 해야 합니까? (0) | 2023.06.22 |
---|---|
버스 오류 대 세그먼트화 오류 (0) | 2023.06.22 |
몽고야?수집 또는 유성.컬렉션? (0) | 2023.06.22 |
Git 로그 날짜 형식 변경 방법 (0) | 2023.06.22 |
Excel 상태 표시줄을 팝업하시겠습니까? (0) | 2023.06.22 |