.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 内只能有一个请求。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值