如何防止 ASP.NET MVC 3 中的重复表单提交?

发布于 2024-11-11 18:34:12 字数 171 浏览 0 评论 0原文

我有一个 razor 视图,它呈现 html 表单并将其发布到服务器。 如果表单值正确,则会将其保存到数据库中。 插入后,我重定向到另一个视图,用户可以在其中进行进一步更改。

现在,用户可以点击浏览器后退按钮并重新提交表单以在数据库中创建另一条记录。

如何防止在我的 MVC 应用程序中重复提交?

I have a razor view that renders a html form and it posts to the server.
If the form values are right then it gets saved to database.
After insertion, I redirect to another view where user can make further changes.

Right now the user can hit browser back button and resubmit the form to create another record in db.

How do I prevent duplicate submission in my MVC app?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

‘画卷フ 2024-11-18 18:34:12

一种解决方案是在表单加载时随机生成的表单上放置一个隐藏的“令牌”字段。当您看到该令牌在创建时返回时,请将其临时存储在某个位置(例如,如果您正在使用会话,则将其存储在会话中)。如果您再次看到同一份表格,则可以假设同一份表格被同时快速提交了两次。

One solution is to put a hidden "token" field on the form that's generated randomly when the form loads. When you see that token come back on creation store it somewhere temporarily (in session if you're using sessions for example). If you see the same one again, you can assume the same form was submitted twice quickly together.

小糖芽 2024-11-18 18:34:12

创建一个 cookie 以在成功时代表该特定页面。如果使用 cookie 重放(浏览器现在会通过每个请求发送该 cookie),您就知道不允许新的尝试。

Create a cookie to represent that particular page when it succeeds. If it is replayed with the cookie (which the browser would now send over with every request) you know not to allow the new attempt.

泅人 2024-11-18 18:34:12

处理 post 请求后将用户重定向到另一个 HttpGet 操作。
这样当用户刷新浏览器时,不会再次调用 post 操作。

返回 RedirectToAction("你的ActionMethod");

Redirect the user to another HttpGet action after handling the post request.
So that when the user refreshes the browser the post action will not be called again.

return RedirectToAction("YourActionMethod");

通知家属抬走 2024-11-18 18:34:12

虽然客户端验证是可能的,但它不够安全。
我不确定这个方法是否适用于 MVC 3,但我所做的是实现一个 ActionFilterAttribute

这里是实现:

 public class PreventFrequentCallsAttribute : ActionFilterAttribute
 {
    public int DelayRequest = 5;

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
            var request = filterContext.HttpContext.Request;      
            var cache = filterContext.HttpContext.Cache;

            var originationInfo = request.ServerVariables["HTTP_X_FORWARDED_FOR"] ?? request.UserHostAddress;
            originationInfo += request.UserAgent;
            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", "Excessive Request Attempts Detected.");                    
            }
            else
            {
                cache.Add(hashValue, originationInfo, null, DateTime.Now.AddSeconds(DelayRequest), Cache.NoSlidingExpiration, CacheItemPriority.Default, null);
            }

            base.OnActionExecuting(filterContext);
    }
}

稍后,在目标控制器中,只需添加此属性:

    [PreventFrequentCalls(3)]
    public PartialViewResult LogOn(LogOnViewModel model)

Although client side validation is possible, it is not secure enough.
I am not sure if this method applies to MVC 3, but what i did is implement a ActionFilterAttribute

here is the implementation:

 public class PreventFrequentCallsAttribute : ActionFilterAttribute
 {
    public int DelayRequest = 5;

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
            var request = filterContext.HttpContext.Request;      
            var cache = filterContext.HttpContext.Cache;

            var originationInfo = request.ServerVariables["HTTP_X_FORWARDED_FOR"] ?? request.UserHostAddress;
            originationInfo += request.UserAgent;
            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", "Excessive Request Attempts Detected.");                    
            }
            else
            {
                cache.Add(hashValue, originationInfo, null, DateTime.Now.AddSeconds(DelayRequest), Cache.NoSlidingExpiration, CacheItemPriority.Default, null);
            }

            base.OnActionExecuting(filterContext);
    }
}

later, in the target controller, just add this attribute:

    [PreventFrequentCalls(3)]
    public PartialViewResult LogOn(LogOnViewModel model)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文