Vue表单提交时如何同时实现CSRF防护和验证码验证?

极客筱萌 阅读 14

在开发登录表单时,我需要同时处理CSRF防护和验证码验证。现在遇到的问题是:当用户刷新验证码时,CSRF令牌没有同步更新,导致表单提交时后端返回验证失败。我尝试在获取验证码接口里携带CSRF令牌,但发现令牌值始终是初始化时的旧值。

这是我的Vue表单组件代码:


<template>
  <form @submit.prevent="submitForm">
    <input v-model="formData.username">
    <input v-model="formData.password">
    <img :src="captchaUrl" @click="refreshCaptcha">
    <input v-model="formData.code">
    <button type="submit">登录</button>
  </form>
</template>

<script>
export default {
  data() {
    return {
      formData: {
        username: '',
        password: '',
        code: '',
        _csrf: '' // 从cookie获取的初始值
      },
      captchaUrl: <code>/api/captcha?_=${Date.now()}</code>
    }
  },
  methods: {
    refreshCaptcha() {
      this.captchaUrl = <code>/api/captcha?_=${Date.now()}</code>;
    },
    async submitForm() {
      try {
        await this.$axios.post('/login', this.formData, {
          headers: {'X-CSRF-Token': this.formData._csrf}
        });
      } catch(err) {
        console.error('验证失败', err);
      }
    }
  }
}
</script>

问题具体出现在:当我点击刷新验证码时,虽然图片更新了,但后端返回的新的CSRF令牌没有被正确捕获。我应该在哪个生命周期阶段重新获取CSRF令牌?是否需要在刷新验证码时同时更新令牌?

我来解答 赞 2 收藏
二维码
手机扫码查看
1 条解答
Air-俊蓓
问题出在CSRF令牌没有实时更新。我的做法是每次刷新验证码时主动从后端获取新令牌,同时更新表单里的_csrf字段。

具体改动如下:

1. 获取验证码的接口应该返回两个值:新的CSRF令牌 + 新的验证码图片地址。比如返回结构是:
{
csrfToken: 'abc123',
captchaUrl: 'data:image/png;base64,...'
}


2. 修改refreshCaptcha方法,用axios请求获取新验证码和新令牌:
async refreshCaptcha() {
const res = await this.$axios.get('/api/captcha');
this.formData._csrf = res.data.csrfToken;
this.captchaUrl = res.data.captchaUrl;
}


3. 初始化的时候也要调用一次refreshCaptcha,这样表单里的_csrf就不会是空值

4. 提交表单的时候只需要传formData,不需要额外带headers。因为后端验证CSRF时会从表单字段里取这个令牌。

这样改完就能保证每次刷新验证码时,CSRF令牌也是最新的。后端需要配合把csrfToken写进响应里。
点赞 4
2026-02-07 16:01