You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Go后端与Vue前端的CSRF防护实现方法问询

嗨Julia,我来帮你一步步搞定Vue+Go栈的CSRF防护,结合gorilla/csrf的最佳实践落地——既然你的Go服务器要负责渲染Vue应用,这中间有几个关键步骤得捋清楚:

第一步:配置Go后端的gorilla/csrf中间件

首先得确保你的Go Web服务器正确集成gorilla/csrf,核心是配置中间件,并且把CSRF Token注入到Vue的入口页面里(因为Go要渲染Vue应用)。

以下是完整的Go代码示例:

package main

import (
    "net/http"
    "html/template"

    "github.com/gorilla/csrf"
    "github.com/gorilla/mux"
)

func main() {
    r := mux.NewRouter()

    // 生产环境务必从环境变量读取密钥,别硬编码!
    csrfKey := []byte("your-32-byte-secret-key-here")
    
    // 配置CSRF中间件,关键参数要注意:
    csrfMiddleware := csrf.Protect(
        csrfKey,
        csrf.Secure(true), // 生产环境必须开启(HTTPS下生效),本地测试可设为false
        csrf.HttpOnly(true), // 开启这个防止XSS窃取cookie中的token
        csrf.FieldName("X-CSRF-Token"), // 和前端axios的请求头名称对应
        csrf.ErrorHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
            http.Error(w, "CSRF Token无效", http.StatusForbidden)
        })),
    )

    // 托管Vue打包后的静态文件(dist目录)
    r.PathPrefix("/static/").Handler(http.StripPrefix("/static/", http.FileServer(http.Dir("./dist/static"))))

    // API路由必须经过CSRF中间件校验
    apiRouter := r.PathPrefix("/api").Subrouter()
    apiRouter.Use(csrfMiddleware)
    apiRouter.HandleFunc("/submit", submitHandler).Methods("POST")

    // 核心:处理根路径,渲染Vue的index.html并注入CSRF Token
    r.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        // 从请求上下文获取当前的CSRF Token
        token := csrf.Token(r)
        // 加载Vue的index.html模板
        tpl, err := template.ParseFiles("./dist/index.html")
        if err != nil {
            http.Error(w, err.Error(), http.StatusInternalServerError)
            return
        }
        // 将Token传入模板,用于在页面中渲染
        templateData := map[string]string{
            "CSRFToken": token,
        }
        tpl.Execute(w, templateData)
    })

    http.ListenAndServe(":8080", r)
}

func submitHandler(w http.ResponseWriter, r *http.Request) {
    // 这里的请求已经通过CSRF校验,放心处理业务逻辑
    w.WriteHeader(http.StatusOK)
    w.Write([]byte("请求处理成功"))
}
第二步:Vue前端获取并携带CSRF Token

因为Go会渲染Vue的入口页面,我们可以在页面中注入Token,然后前端读取并在请求中携带:

1. 在Vue的入口页面注入Token

修改Vue项目的public/index.html(开发环境),或者打包后的dist/index.html(生产环境),添加一个隐藏的input标签(和你原代码的选择器对应):

<!-- 隐藏input,用于存储CSRF Token -->
<input type="hidden" name="gorilla.csrf.Token" value="{{.CSRFToken}}">

如果你觉得input不够优雅,也可以用meta标签:<meta name="csrf-token" content="{{.CSRFToken}}">,后续前端读取方式对应调整即可。

2. 调整Axios配置,携带Token

你的原代码已经接近正确,只需要做一点小调整,确保能稳定获取Token,同时处理Token过期的情况:

// 获取CSRF Token(和页面中的标签对应)
let csrfToken = document.getElementsByName("gorilla.csrf.Token")[0].value;
// 如果用meta标签的话,改成:
// let csrfToken = document.querySelector('meta[name="csrf-token"]').content;

// 创建Axios实例,全局携带CSRF Token
const instance = axios.create({
  baseURL: "/api/", // 用相对路径避免跨域问题
  timeout: 1000,
  headers: { "X-CSRF-Token": csrfToken }
});

// 发起POST请求的逻辑
try {
  const resp = await instance.post(endpoint, formData);
  // 处理响应数据
  console.log(resp.data);
} catch (err) {
  // 处理异常:如果是CSRF Token无效/过期,刷新页面重新获取
  if (err.response?.status === 403) {
    window.location.reload();
  } else {
    // 其他错误处理逻辑
    console.error("请求失败:", err);
  }
}
关键安全注意事项
  • 生产环境必开HTTPS:一定要保持csrf.Secure(true),确保CSRF Cookie只在HTTPS连接下传输。
  • 避免直接读取Cookie:尽量用页面注入Token的方式(而非让前端读取Cookie),因为HttpOnly(true)可以防止XSS攻击窃取Cookie中的Token,这是更安全的做法。
  • 跨域场景特殊处理:如果Vue和Go不在同一域名下,需要配置CORS,允许X-CSRF-Token请求头传递,同时设置Cookie的SameSite属性为Lax或None(跨域时)。

内容的提问来源于stack exchange,提问作者Julia12

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:25:15