返回

前端如何进行重复提交防护?

前端

如今,web开发中经常使用ajax从后端获取数据,提交数据。对于有些游戏爱好者或手速较快的用户而言,一个按钮触发click事件可以触发多次。有经验的前端开发者肯定会使用防止重复提交的方式避免重复提交数据。

那么在前端应该如何做才能避免重复提交呢?本文将讨论多种前端重复提交防护技术,帮助您保护您的Web应用程序免受此类攻击。

按钮禁用

一种简单的方法是禁用按钮,直到服务器响应为止。这可以防止用户在收到响应之前再次单击按钮。

function submitForm(e) {
  e.preventDefault();

  // 禁用按钮
  document.querySelector('button[type="submit"]').disabled = true;

  // 发送表单数据到服务器
  fetch('/submit-form', {
    method: 'POST',
    body: new FormData(document.querySelector('form'))
  })
  .then(res => {
    // 处理服务器响应

    // 启用按钮
    document.querySelector('button[type="submit"]').disabled = false;
  })
  .catch(err => {
    // 处理错误

    // 启用按钮
    document.querySelector('button[type="submit"]').disabled = false;
  });
}

网络请求标识符

另一种方法是使用网络请求标识符来跟踪正在进行的请求。当用户单击按钮时,可以生成一个唯一的标识符并将其存储在本地存储中。然后,在发送请求之前,可以检查本地存储以查看是否已经发送了具有相同标识符的请求。如果是,则可以阻止重复请求。

function submitForm(e) {
  e.preventDefault();

  // 检查本地存储中是否有正在进行的请求标识符
  const requestId = localStorage.getItem('request-id');
  if (requestId) {
    // 已经发送了请求,因此阻止重复请求
    return;
  }

  // 生成一个唯一的标识符并将其存储在本地存储中
  const newRequestId = Date.now().toString();
  localStorage.setItem('request-id', newRequestId);

  // 发送表单数据到服务器
  fetch('/submit-form', {
    method: 'POST',
    body: new FormData(document.querySelector('form'))
  })
  .then(res => {
    // 处理服务器响应

    // 删除本地存储中的请求标识符
    localStorage.removeItem('request-id');
  })
  .catch(err => {
    // 处理错误

    // 删除本地存储中的请求标识符
    localStorage.removeItem('request-id');
  });
}

页面级锁定

页面级锁定是另一种防止重复提交的技术。当用户单击按钮时,可以将整个页面锁定,以防止用户执行任何其他操作。当服务器响应时,可以解锁页面。

function submitForm(e) {
  e.preventDefault();

  // 锁定页面
  document.body.style.pointerEvents = 'none';

  // 发送表单数据到服务器
  fetch('/submit-form', {
    method: 'POST',
    body: new FormData(document.querySelector('form'))
  })
  .then(res => {
    // 处理服务器响应

    // 解锁页面
    document.body.style.pointerEvents = 'auto';
  })
  .catch(err => {
    // 处理错误

    // 解锁页面
    document.body.style.pointerEvents = 'auto';
  });
}

节流和防抖

节流和防抖是两种可以用来限制函数调用频率的技术。节流会在一段时间内只允许函数被调用一次,而防抖会在一段时间内只允许函数被调用最后一次。这两种技术都可以用来防止重复提交。

// 节流
function throttle(func, wait) {
  let lastCall = 0;

  return function(...args) {
    const now = Date.now();
    if (now - lastCall >= wait) {
      lastCall = now;
      func(...args);
    }
  }
}

// 防抖
function debounce(func, wait) {
  let timeout;

  return function(...args) {
    clearTimeout(timeout);
    timeout = setTimeout(() => {
      func(...args);
    }, wait);
  }
}

// 使用节流或防抖来防止重复提交
const submitForm = throttle(submitForm, 500);

验证码

验证码是一种常用的防止重复提交的技术。当用户提交表单时,需要输入一个验证码。验证码是一个随机生成的字符串,通常由数字和字母组成。验证码可以防止自动提交脚本提交重复请求。

function submitForm(e) {
  e.preventDefault();

  // 获取验证码值
  const captchaValue = document.querySelector('input[name="captcha"]').value;

  // 发送表单数据和验证码值到服务器
  fetch('/submit-form', {
    method: 'POST',
    body: new FormData(document.querySelector('form'))
  })
  .then(res => {
    // 处理服务器响应

    // 重置验证码
    document.querySelector('input[name="captcha"]').value = '';
  })
  .catch(err => {
    // 处理错误

    // 重置验证码
    document.querySelector('input[name="captcha"]').value = '';
  });
}

希望本文对您有所帮助!如果您有任何其他问题,请随时与我联系。