.net core 中如何有效屏蔽重复提交
Posted dotNET跨平台
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了.net core 中如何有效屏蔽重复提交相关的知识,希望对你有一定的参考价值。
咨询区
Guilherme Ferreira:
我通过 post 方式向我的一个webapi中提交数据,然后插入到数据库中,在 ui端,当用户点击某一个 button 之后,代码会将 button 禁用,但因为某些原因,点击按钮的速度比禁用按钮的函数还要快,这就造成了post两次的情况,也就插入了两条同样的数据。
在客户端我用 axios 来做 post 提交,请问我如何在 server 端规避这种事情?
回答区
Christian Gollhardt:
前段时间刚好遇到了这个场景,我创建了一个 ActionFilter,然后使用了 Anti Fogery Token
,参考如下代码:
首先启用 session。
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = Context => false;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
services.AddMemoryCache();
services.AddSession(options => {
// Set a short timeout for easy testing.
options.IdleTimeout = TimeSpan.FromMinutes(10);
options.Cookie.HttpOnly = true;
// Make the session cookie essential
options.Cookie.IsEssential = true;
});
然后就可以 use 了。
app.UseSession();
接下来定义一个防重复提交的 Attribute 。
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class PreventDoublePostAttribute : ActionFilterAttribute
{
private const string UniqFormuId = "LastProcessedToken";
public override async void OnActionExecuting(ActionExecutingContext context)
{
IAntiforgery antiforgery = (IAntiforgery)context.HttpContext.RequestServices.GetService(typeof(IAntiforgery));
AntiforgeryTokenSet tokens = antiforgery.GetAndStoreTokens(context.HttpContext);
if (!context.HttpContext.Request.Form.ContainsKey(tokens.FormFieldName))
{
return;
}
var currentFormId = context.HttpContext.Request.Form[tokens.FormFieldName].ToString();
var lastToken = "" + context.HttpContext.Session.GetString(UniqFormuId);
if (lastToken.Equals(currentFormId))
{
context.ModelState.AddModelError(string.Empty, "Looks like you accidentally submitted the same form twice.");
return;
}
context.HttpContext.Session.Remove(UniqFormuId);
context.HttpContext.Session.SetString(UniqFormuId, currentFormId);
await context.HttpContext.Session.CommitAsync();
}
}
然后在需要该验证规则的 Action 上进行标注。
[HttpPost]
[PreventDoublePost]
public async Task<IActionResult> Edit(EditViewModel model)
{
if (!ModelState.IsValid)
{
//PreventDoublePost Attribute makes ModelState invalid
}
throw new NotImplementedException();
}
关于如何生成 Anti Fogery Token
,可以看下msdn: https://docs.microsoft.com/en-us/aspnet/core/security/anti-request-forgery?view=aspnetcore-2.2#javascript
点评区
这是一个非常常见的需求,除了这种做法,通常用带有过期时间的cache来做,也是可以的,比如 3s 内只能有一个请求。
以上是关于.net core 中如何有效屏蔽重复提交的主要内容,如果未能解决你的问题,请参考以下文章
.net core savechanges 网络不好情况下,如何防止用户连击重复提交数据?
需要一种有效的方法来避免使用 Laravel 5 重复代码片段