(15)使用CAPTCHA去防止恶意软件自动提交评论

问题

有种不太幸运的情况,有人用自动程序去提交表单,在整个互联网中造成大量的垃圾。为了防止这种情况的方法之一,是使用一个验证码---CAPTCHA:全自动区分计算机和人类的图灵测试,这迫使用户把生成的文字输入到文本框。

(译者:CAPTCHA是一种更人性化的验证码,可以通过视觉和听觉来区分post的请求是人类还是计算机发出的)

解决方案

从NuGet安装ASP.NET Web Helpers Library  从而在BookCommentsController实现防止而已添加书评的功能。 

讨论

需要安装一个新的类包,使在表单上应用CAPTCHA成为可能。微软已经创建了一个NuGet web helpers 类包含了CAPTCHA,让我们很容易实施并且验证用户输入的CAPTCHA。先打开MVC项目,在vs中选择Tools→LibraryPackage Manager→Add Library Package Reference。点击左边的Online,在第一页的下方您就可以发现 Asp.net web helpers Library。点击安装。

在我们的例子里。那些自动发送post请求的软件一般会用在图书评论上。所以是这里最完美的添加CAPTCHA的地方。在开始之前你必须在RECAPTCHA website为你的域名注册。(译者:一般要用一个gmail账户。我们使用自己已有的或者重新注册一个,在这里由于我们的项目是在本机练习使用的,我就为我的localhost注册)。注册成功之后你可以得到一个公钥(public key)和一个私钥(private key)。

提示:如果你不使用Ajax去包含CAPTCHA,你可以通过以下两行代码改变你的view:

双击代码全选
1
2
@using Microsoft.Web.Helpers;
@ReCaptcha.GetHtml("<你的公钥>", "<你的私钥>")
 

 

一旦配置完成了,是时候开始更新我们的代码了。我们需要在BookComments/Index view里做一些小更改。这个view是前一段创建的,用于使用ajax提交书评。这个Ajax需要更新成:当请求完毕,调用javascript函数去显示CAPTCHA按钮。代码如下:

双击代码全选
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
@model IEnumerable< MvcApplication.Models.BookComment >
@{
     ViewBag.Title = "Index";
}
< h2 >
     Index</ h2 >
< p >
     @Ajax.ActionLink("Create New", "Create", new
{
     BookId = ViewBag.BookId
},
new AjaxOptions { UpdateTargetId = "AddComment" })
</ p >
< div id = "AddComment" >
</ div >
< script type = "text/javascript" src =
</ script >
< script type = "text/javascript" >
     function DisplayCaptcha() {
         Recaptcha.destroy();
         Recaptcha.create("6Le27coSAAAAAK8KqpUIGvz3qTDXGa9ud9Xst4yY", "captcha", {});//你的公钥
 
     }
</ script >
< table >
     < tr >
         < th >
             Comment
         </ th >
         < th >
             Created
         </ th >
     </ tr >
     @foreach (var item in Model)
     {
         < tr >
             < td >
                 @Html.DisplayFor(modelItem => item.Comment)
             </ td >
             < td >
                 @Html.DisplayFor(modelItem => item.Created)
             </ td >
             < td >
                 @Html.DisplayFor(modelItem => item.Book.Title)
             </ td >
         </ tr >
     }
</ table >
 

现在,去更新BookComments/create view 。首先添加一个地点去展示CAPTCHA.然后添加一个新的HTML 错误消息,当他们输入错误的验证码时,会提示错误。最后在ReloadComment  javascript 函数里更改代码成不自动reload 书评(仅仅当没错的时候才reload)。

双击代码全选
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
@model MvcApplication.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/Index?BookId=@ViewBag.BookId");
         }
     }
</ 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里去,view把它展示出来。

双击代码全选
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using MvcApplication.Models;
using Microsoft.Web.Helpers;
using MvcApplication.Models;
namespace MvcApplication.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(
             "6Le27coSAAAAAM6kZnXU8m1j9");//你的私钥
 
             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);
         }
     }
}
 

(译者:下图是我实践之后的截图,不知道这个CAPTCHA的背景样式是否能自定义,如果可以的话就太酷了!)

 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Lin&Yi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值