[翻訳]ASP.NET MVC 3が開発した20の秘訣(十五)[20 Recipes for Programming MVC 3]:ピクチャ検証コード(CAPTCHA)の有効化

16624 ワード

議題
多くの自動プログラムがフォームを自動的に提出し、インターネット上で大量のゴミデータを発生させることを防止するために、ユーザーが提出するときにテキストボックスに画像に表示される正しい文字を入力しなければならないグラフィック検証コード(CAPTCHA:Completely Automated Public Turing test to tell Computers and Humans Apart)を実現しました.
 
ソリューション
BookCommentsControlコントローラにASPをインストールする.NET Web Helper LibraryでNuGetが提供するCAPTCHA.
 
ディスカッション
新しいLibrary Packageが含まれ、フォームにCAPTCHAが追加されます.MicrosoftはNuGet Web Helpers LibraryにCAPTCHAクラスを内蔵しており、ユーザー入力を検証するCAPTCHAを容易に実現できます.
 
Visual StudioのMVCアプリケーション項目で、メニュー「ツール」→「Library Package Manager」→「Add Library Package Reference」をクリックします.読み込み後、左側で「Online」カテゴリを選択し、トップページで「microsoft-web-helpers」を選択し、リストにない場合は右上隅で検索します.見つけたら「Install」をクリックします.
 
最も典型的なフォームの提出例はコメントの提出です.以前のレシピでは、書籍コメントを追加することがCAPTCHAを追加する完璧な事例でした.開始する前に、ドメイン名をRECAPTCHAサイトに登録する必要があります.登録が完了すると、あなたのサイト専用の秘密鍵と公開鍵が届きます.将来の使用のためにコピーして保存します.
 
設定が完了したら、コードの変更を開始します.BookComments/Indexビューで小さな変更をすればいいです.以前に作成したコメントの追加ページです.Ajaxリクエストを開始するとCAPTCHAボタンが表示され、リクエストが完了すると「DisplayCaptcha」というJavascriptメソッドが呼び出されます.
@model IEnumerable<MvcApplication4.Models.BookComment>
@{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<p>
@Ajax.ActionLink("Create New", "Create", new {
BookId = ViewBag.BookId },
new AjaxOptions { UpdateTargetId = "AddComment",
OnComplete = "DisplayCaptcha" })
</p>
<div id="AddComment"></div>
...
<script type="text/javascript" src=
"http://www.google.com/recaptcha/api/js/recaptcha_ajax.js"
>
</script>
<script type="text/javascript">
function DisplayCaptcha() {
Recaptcha.destroy();
Recaptcha.create(
"<your_public_key>", "captcha", {});
}

</script>

BookComments/Createビューを少し変更します.まず、ユーザーがエラーを入力したときにエラーメッセージを表示する領域表示CAPTCHAと新しいHTMLタグを作成する必要があります.最後に、ReloadCommentメソッドを変更して、自動再読み込みなしでCAPTCHAを表示します(エラーがない場合のみ).
@model MvcApplication4.Models.BookComment
@{
ViewBag.Title = "Create";
}
<h2>Create</h2>
@section JavascriptAndCSS {
<script src="@Url.Content("~/Scripts/jquery.validate.min.js")"
type
="text/javascript"></script>
<script src="
@Url.Content("
~/Scripts/jquery.validate.unobtrusive.min.js")"
type
="text/javascript"></script>
}
<script type="text/javascript">
function ReloadComments() {
var reload = "@ViewBag.RefreshComments";
if (reload == "False") {
DisplayCaptcha();
}
else {
$(
"#Comments").load(
"/BookComments/[email protected]");
}
}
</script>
@using (Ajax.BeginForm(new AjaxOptions {
UpdateTargetId="AddComment", OnComplete="ReloadComments" }))
{
@Html.Hidden("BookId", (int)ViewBag.BookId);
@Html.ValidationSummary(true)
<fieldset>
<legend>BookComment</legend>
<div class="editor-label">
@Html.LabelFor(model => model.Comment)
</div>
<div class="editor-field">
@Html.TextAreaFor(model => model.Comment)
@Html.ValidationMessageFor(model => model.Comment)
</div>
<div class="editor-label">
Are you human?
</div>
<div class="editor-field">
<div id="captcha"></div>
@Html.ValidationMessage("Captcha")
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>

}

最後に、BookCommentsController認証ユーザーが入力したCAPTCHAを変更する必要があります.検証に失敗した場合は、ModelStateにエラーメッセージを追加し、ビューに戻って表示します.
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using MvcApplication4.Models;
using Microsoft.Web.Helpers;

namespace MvcApplication4.Controllers
{
public class BookCommentsController : Controller
{
private BookDBContext db = new BookDBContext();

//
// GET: /BookComments/
public ActionResult Index(int BookId)
{
ViewBag.BookId = BookId;
var bookcomments = db.BookComments.Include(
b => b.Book).Where(b => b.BookId == BookId);
return PartialView(bookcomments.ToList());
}

//
// GET: /BookComments/Create
public ActionResult Create(int BookId)
{
ViewBag.BookId = BookId;
ViewBag.RefreshComments = false;
return PartialView();
}

//
// POST: /BookComments/Create
[HttpPost]
public ActionResult Create(BookComment bookcomment)
{
ViewBag.RefreshComments = false;
var captchaSuccess = ReCaptcha.Validate(
"<your_private_key>");
if (ModelState.IsValid && captchaSuccess)
{
bookcomment.Created = DateTime.Now;
db.BookComments.Add(bookcomment);
db.SaveChanges();
ViewBag.RefreshComments = true;
}

// if captcha failed add error message
if (!captchaSuccess)
{
ModelState.AddModelError("Captcha",
"Invalid CAPTCHA");
}
ViewBag.BookId = bookcomment.BookId;
return PartialView(bookcomment);
}

protected override void Dispose(bool disposing)
{
db.Dispose();
base.Dispose(disposing);
}
}
}

リファレンス
原書の住所   ブックソース