luck18新利




    luck18新利

    网站(zhàn)应用程序防(fáng)止数据重(chóng)复提交

    发布于(yú): 2025-07-07    浏览: 64    作者:系统管理(lǐ)员

    一、前(qián)端防护策(cè)略(luè)(减少无(wú)效请求)

    1.按钮禁用(yòng)与状态反馈

    ·点击后立即禁用按钮,阻止二次点(diǎn)击,并(bìng)添(tiān)加加载动画提示用(yòng)户:document.getElementById("btnSubmit").addEventListener("click", function() {

    this.disabled = true;

    this.classList.add("loading-spinner"); // 添加加载样式

    });

    2.防抖(Debounce)与请求锁

    ·通过标志位或(huò)定时器限制(zhì)短时间(jiān)内(nèi)的重(chóng)复提交:

    let isSubmitting = false;functionsubmitForm() {

    if (isSubmitting) return;    

    isSubmitting = true;// 执行提交逻(luó)辑

    }

    ·框(kuàng)架中可使用lodash.debounce优化

    3.异步提交(jiāo) + Loading提示(shì)

    ·使用Ajax提交数(shù)据(jù),配合模态框或进度条增强(qiáng)用户体验:

    printf("hello world!");$("#form").submit(function(e) {   

     e.preventDefault();    

    $("#loadingModal").show(); // 显(xiǎn)示加载提示(shì)    

    $.post("/submit", $(this).serialize(), function() {        

    $("#loadingModal").hide();    

    });

    });



    二、后端幂等性控制(zhì)(核心防御(yù))

    1.Token令牌机制

    ·流程(chéng):生成(chéng)页面时创(chuàng)建唯(wéi)一Token(如(rú)GUID)存入Session,嵌入表单隐藏域;提交时校验Token有效性并立即销毁。


    // ASP.NET MVC 示(shì)例public ActionResult SubmitForm(){

    string token = Guid.NewGuid().ToString();    

    Session["SubmitToken"] = token;    

    ViewBag.Token = token; // 传递到视(shì)图(tú)

    }
    [HttpPost]

    public ActionResult SubmitForm(FormModel model, string token){

    if (Session["SubmitToken"]?.ToString() != token) return Content("重复提交拒绝");    

    Session.Remove("SubmitToken");// 处理业务(wù)

    }

    ·优势:有效防御刷新、后退(tuì)导致的重(chóng)复提交


    2.幂等键(Idempotency Key)

    ·客户端生成唯一(yī)Key(如GUID)放(fàng)入请求头,服务端通过缓存(Redis/MemoryCache)校验:

    // ASP.NET Core 过滤器示例(lì)

    publicclassIdempotencyFilter : IAsyncActionFilter{   

     public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next){        

    var key = context.HttpContext.Request.Headers["Idempotency-Key"].FirstOrDefault();        if (_cache.TryGetValue(key, out _))    context.Result = new BadRequestResult();        

    else    _cache.Set(key, true, TimeSpan.FromMinutes(5));        

    await next();    

    }

    }


    3.重定(dìng)向模式(PRG: Post-Redirect-Get)

    ·提交成功后返回302重定向至结果页,刷新时(shí)仅重发GET请求(qiú),避(bì)免重复POST。


     三(sān)、数据库与(yǔ)架构层防护

    1.数据(jù)库唯一约束(shù)

    ·为(wéi)业务关(guān)键字(zì)段(duàn)(如订单(dān)号、用户邮箱)添加(jiā)唯一索引,从底层(céng)阻止(zhǐ)重(chóng)复数据:

    ALTERTABLE Orders ADDUNIQUE (OrderNumber);



    2.分(fèn)布(bù)式锁(Redis)

    ·以“用(yòng)户(hù)ID + 操作类型(xíng)”为Key加锁,确保并(bìng)发(fā)请求仅一(yī)个生(shēng)效:

    // Redis锁示例

    if (redisLock.AcquireLock(userId + "_submit"TimeSpan.FromSeconds(10))){    // 执行业务(wù)    

    redisLock.ReleaseLock();

    }


    3.操作状态校(xiào)验

    ·更(gèng)新数据前检查状(zhuàng)态(tài)(如订单是否已(yǐ)处理),避免重复更(gèng)新:

    UPDATE Orders SET Status ='Paid'WHERE Id =100AND Status ='Pending';



    总结

    ·基(jī)础方案:前端按钮(niǔ)禁用 + 后(hòu)端Token校验(yàn)(覆盖90%场(chǎng)景)

    ·高可靠场(chǎng)景(jǐng):补充数据库(kù)唯一索引与Redis分布式(shì)锁

    ·用户体验优化:加载动画与防抖减(jiǎn)少用户焦虑性(xìng)点击





    在线客服

    售前咨询(xún)

    售(shòu)后服务

    投诉/建议(yì)

    服务(wù)热线
    0731-83091505
    18874148081

    luck18新利

    luck18新利