beego的xsrf防护需显式开启并配全参数:在conf/app.conf中设enablexsrf=true、xsrfkey(≥32字节随机串)、xsrfexpire(秒);或在main.go中用beego.bconfig.webconfig配置三者;模板中须调用xsrfformhtml()注入隐藏域,前后端分离时改用x-xsrftoken/x-csrftoken请求头传递。

Beego 的 XSRF 防护默认不启用,必须显式开启并配对 token 传递方式,否则所有 POST/PUT/DELETE 请求会直接 422 拒绝。
如何在 beego 中正确开启 XSRF 防护
beego 不会在启动时自动启用 XSRF,必须手动配置。两种等效方式任选其一,但不能只设 enablexsrf = true 而漏掉 xsrfkey —— 缺失 key 会导致校验逻辑跳过或 panic:
- 在配置文件(如
conf/app.conf)中添加三行:enablexsrf = true xsrfkey = "61oETzKXQAGaYdkL5gEmGeJJFuYh7EQnp2XdTP1o" xsrfexpire = 3600
- 或在
main.go中beego.Run()前设置:beego.BConfig.WebConfig.EnableXSRF = true beego.BConfig.WebConfig.XSRFKey = "61oETzKXQAGaYdkL5gEmGeJJFuYh7EQnp2XdTP1o" beego.BConfig.WebConfig.XSRFExpire = 3600
注意:xsrfkey 必须是至少 32 字节的随机字符串,硬编码默认值(如 "beegoxsrf")极不安全;xsrfexpire 单位为秒,默认 60 秒,太短易导致用户表单未提交就失效。
模板里怎么插入 XSRF token
开启后,beego 会为每个用户下发一个 _xsrf cookie,但服务端不会自动注入到表单中——你必须显式调用 XSRFFormHTML() 并渲染进 HTML:
- Controller 中传入模板:
func (this *HomeController) Get() { this.Data["xsrfdata"] = template.HTML(this.XSRFFormHTML()) } - 模板中使用(必须放在
<form></form>内):
XSRFFormHTML() 生成的是一个隐藏域:<input type="hidden" name="_xsrf" value="...">。若漏掉这步,请求体里没有 _xsrf 字段,beego 会立即返回 422 状态码。
前后端分离场景下如何传 token
当前端部署在独立域名(如 https://fe.example.com),而 beego 后端在 https://api.example.com 时,浏览器同源策略阻止 cookie 自动携带 _xsrf。此时需改用请求头方式:
- 前端从登录接口或专门的
/xsrf-token接口获取 token(该接口需在 controller 中调用this.XSRFToken()返回纯字符串) - 后续所有敏感请求带上 header:
X-Xsrftoken: abcdef123456...
或X-CsrfToken: abcdef123456...
- beego 源码中
CheckXSRFCookie()会按顺序检查:_xsrf表单字段 →X-Xsrftokenheader →X-CsrfTokenheader
注意:cookie 和 header 两种方式互斥不可混用;若同时存在,beego 只取第一个非空值。别试图从 cookie 中读取再手动塞 header —— _xsrf cookie 是 httpOnly 的,JS 无法访问。
为什么 POST 请求总是 417 或 422
两个最常见原因:
-
422 Unprocessable Entity:请求里完全没带_xsrf字段或 header,说明前端漏传、模板未渲染、或 AJAX 请求没设 header -
417 Expectation Failed:token 值存在,但和当前 session 存储的不匹配,通常因为:- 用户长时间未操作导致 token 过期(
xsrfexpire到期) - 多标签页并发提交,旧 token 被新 token 覆盖
- 服务端重启或 session 存储丢失(如使用内存 session 且未做持久化)
- 用户长时间未操作导致 token 过期(
调试时可临时在 controller 中打印:
beego.Debug("current xsrf:", this.Ctx.Input.Header("X-Xsrftoken"))
beego.Debug("session xsrf:", this._xsrfToken) 对比值是否一致。真正上线时切勿留这类日志。











