您的位置:首页 > 编程语言 > ASP

在asp.net mvc中使用ActionFilter防止重复提交

2014-06-25 14:34 567 查看
防止重复提交的好处:可以预防恶意用户发重复的帖子和垃圾信息出现.

解决方案:

需要创建一个自定义的ActionFilter,重写OnActionExecuting方法

public class PreventSpamAttribute: ActionFilterAttribute

{

public override void OnActionExecuting (ActionExecutingContext filterContext)

{ base.OnActionExecuting (filterContext);

}

}

定义几个属性

一个属性来处理请求之间的延迟。

有一种机制来唯一识别用户的请求(和他们的目标)。

一种机制来存储这些信息,因此,它是访问请求发生时。

ModelState的信息显示错误的输出属性来处理。

让我们开始增加的延迟,这将仅仅是一个整数的值,将表明(以秒为单位)请求一个特定的控制器动作以及一些额外的属性,将存储的信息处理显示的错误和无效的请求重定向之间允许的最小延迟:

public class PreventSpamAttribute : ActionFilterAttribute

{

//处理请求之间的延迟

public int DelayRequest = 10;

//防止多次请求时的错误提示信息

public string ErrorMessage = "Excessive Request Attempts Detected.";

//出错时URL重定向

public string RedirectURL;

public override void OnActionExecuting(ActionExecutingContext filterContext)

{

base.OnActionExecuting(filterContext);

}

}

确定发出请求的用户和他们的目标

下一步,我们将需要一种方法来存储当前有关用户的信息,并在他们的要求是源于这样我们就可以正确识别。做到这一点的方法之一是将得到一些识别有关用户的信息(如IP地址)“ HTTP_X_FORWARDED_FOR “头(如果不存在,” REMOTE_ADDR “标头值回落)和可能附加用户代理(使用“ USER_AGENT “头),以及进一步磨练我们的用户。

public override void OnActionExecuting(ActionExecutingContext filterContext)

{

//存储 HttpContext

var request = filterContext.HttpContext.Request;

//获取IP请求者的IP地址

var originationInfo = request.ServerVariables["HTTP_X_FORWARDED_FOR"] ?? request.UserHostAddress;

//Append the User Agent

originationInfo += request.UserAgent;

//目标URL信息

var targetInfo = request.RawUrl + request.QueryString;

base.OnActionExecuting(filterContext);

}

生成一个Hash来标识唯一请求

现在,我们有独特的要求为我们的用户和他们的目标信息,我们可以用它来生成哈希将存储和使用,以确定是否垃圾邮件的请求后,可能是有效的。

为此,我们将使用。NET加密库(System.Security.Cryptography)你的字符串值来创建一个简单的MD5哈希值,所以你需要ActionFilter正在申报包括适当的using语句:

using System.Security.Cryptography;

我们可以利用LINQ来执行我们的字符串很短的小单行转换到一个散列字符串,使用这条线:

//Generate a hash for your strings (this appends each of the bytes of the value into a single hashed string

var hashValue = string.Join("", MD5.Create().ComputeHash(Encoding.ASCII.GetBytes(originationInfo + targetInfo)).Select(s => s.ToString("x2")));

内存储的哈希缓存

我们可以使用散列字符串作为重点,将被保存在缓存中,以确定是否即将请求是重复的,并进行相应的处理。

public override void OnActionExecuting(ActionExecutingContext filterContext)

{

//Store our HttpContext

var request = filterContext.HttpContext.Request;

//Store our HttpContext.Cache

var cache = filterContext.HttpContext.Cache;

//Grab the IP Address from the originating Request

var originationInfo = request.ServerVariables["HTTP_X_FORWARDED_FOR"] ?? request.UserHostAddress;

//Append the User Agent

originationInfo += request.UserAgent;

//目标URL信息

var targetInfo = request.RawUrl + request.QueryString;

//创建希哈值

var hashValue = string.Join("", MD5.Create().ComputeHash(Encoding.ASCII.GetBytes(originationInfo + targetInfo)).Select(s => s.ToString("x2")));

//如果希哈值在缓存中,(重复提交)

if (cache[hashValue] != null)

{

//添加错误信息

filterContext.Controller.ViewData.ModelState.AddModelError("ExcessiveRequests", ErrorMessage);

}

else

{

//使用希哈值的key添加一个空对象到缓存中(决定是否过期)

//if the Request is valid or not

cache.Add(hashValue, hashValue, null, DateTime.Now.AddSeconds(DelayRequest), Cache.NoSlidingExpiration, CacheItemPriority.Default, null);

}

base.OnActionExecuting(filterContext);

}

应用

//Displays your form initially

public ActionResult YourPage()

{

return View(new TestModel());

}

[HttpPost]

[PreventSpam]

public ActionResult YourPage(TestModel yourModel)

{

//If your Model was valid - output that it was successful!

if (ModelState.IsValid)

{

return Content("Success!");

}

//Otherwise return the model to the View

else

{

return View(yourModel);

}

}

//This action can only be accessed every 60 seconds and any additional requests within that timespan will

//notify the user with a custom message.

[PreventSpam(DelayRequest=60,ErrorMessage="You can only create a new widget every 60 seconds.")]

public ActionResult YourActionName(YourModel model)

{

//Your Code Here

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: