zoukankan      html  css  js  c++  java
  • .NET Core 屏蔽重复提交

    加入session支持

    public void ConfigureServices(IServiceCollection services)
    {
        // add session support
        services.Configure<CookiePolicyOptions>(options =>
        {
            options.CheckConsentNeeded = context => false;
            options.MinimumSameSitePolicy = Microsoft.AspNetCore.Http.SameSiteMode.None;
        });
    
        services.AddSession(options =>
        {
            options.IdleTimeout = TimeSpan.FromSeconds(100);
            options.Cookie.HttpOnly = true;
            options.Cookie.IsEssential = true;
        });
    
        // 没有下面这句,启动会失败,
        // 报这个错: InvalidOperationException: Unable to resolve service for type 'Microsoft.Extensions.Caching.Distributed.IDistributedCache' while attempting to activate 'Microsoft.AspNetCore.Session.DistributedSessionStore
        services.AddDistributedMemoryCache();
        // 因为PreventDoublePostAttribute用到了IAntiforgery,所以这里还要加
        services.AddAntiforgery(options => options.HeaderName = "X-XSRF-TOKEN");
        ...
    }
    
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IAntiforgery antiforgery)
    {
        ...
        app.UseStaticFiles();
        // add session pipepline
        app.UseSession();
        ...
    }
    

    引入PreventDoublePostAttribute属性

    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
    public class PreventDoublePostAttribute : ActionFilterAttribute
    {
        private const string UniqFormuId = "LastProcessedToken";
        public override async void OnActionExecuting(ActionExecutingContext context)
        {
            IAntiforgery antiforgery = context.HttpContext.RequestServices.GetService(typeof(IAntiforgery)) as IAntiforgery;
    
            if (antiforgery == null)
                return;
    
            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();
        }
    }
    

    使用

    [HttpPost]
    [PreventDoublePost]
    public ActionResult<TodoItem> Create([FromForm] TodoItem item)
    {
        AllItems.Add(item);
        return CreatedAtRoute("GetTodo", new { id = item.Id }, item);
    }
    

    测试

    # test post 
    POST https://localhost:44352/TodoItem/ HTTP/1.1
    content-type: application/x-www-form-urlencoded
    cache-control: no-cache
    
    __RequestVerificationToken=form_id_1
    &id=86336
    &Summary=ttt
    ###
    

    既然PreventDoublePostAttribute属性只使用了tokens.FormFieldName,那么hardcode一个hidden formid应该也可以,这样就不需要AntiForgery了。
    再说AntiForgery也不是这么用的。

    参考

    --------------------------- 知道的更多,不知道的也更多 ---------------------------
  • 相关阅读:
    [kuangbin带你飞]专题七 线段树
    [kuangbin带你飞]专题六 最小生成树
    [kuangbin带你飞]专题五 并查集
    [kuangbin带你飞]专题四 最短路练习
    [kuangbin带你飞]专题三 Dancing Links
    [kuangbin带你飞]专题二 搜索进阶
    [kuangbin带你飞]专题一 简单搜索
    常用算法模板
    ACM程序设计选修课——Problem E:(ds:图)公路村村通(Prim)
    HDU——5667Sequence(矩阵快速幂+费马小定理应用)
  • 原文地址:https://www.cnblogs.com/mryux/p/15434744.html
Copyright © 2011-2022 走看看