Buffalo中AJAX请求需手动将CSRF令牌设为X-CSRF-Token请求头,优先从<meta name="csrf-token">标签读取,不可放URL或body;服务端仅校验该请求头,且令牌绑定会话,过期需重登录。

Buffalo 中 CSRF 令牌怎么塞进 AJAX 请求头
Buffalo 默认启用 CSRF 保护,所有非 GET/HEAD 的请求都必须携带有效 _csrf 令牌。AJAX 请求绕过表单自动提交机制,所以得手动传——不是加在 URL 或 body 里,而是设在请求头中。
关键点:Buffalo 把令牌存在 cookie(_csrf)里,也默认通过 meta 标签注入到 HTML 的 <head> 中(如 <meta name="csrf-token" content="xxx"></meta>),这是最稳妥的读取来源。
- 不要从 cookie 手动解析
_csrf值——浏览器同站策略下可能被HttpOnly拦住(Buffalo 默认不设HttpOnly,但依赖它不安全) - 服务端模板渲染时,确保 layout 模板里有
<meta name="csrf-token" content="">(Go 模板)或等效的csrf_tag()(Pop/Soda 模板) - 前端用
document.querySelector('meta[name="csrf-token"]')?.getAttribute('content')取值,比硬编码或从隐藏 input 读更可靠
jQuery AJAX 怎么自动带 CSRF 头
如果你还在用 jQuery(比如老项目),可以用 $.ajaxSetup 统一注入,避免每个 $.post 都重复写头。
$.ajaxSetup({
beforeSend: function(xhr) {
const token = document.querySelector('meta[name="csrf-token"]')?.getAttribute('content');
if (token) {
xhr.setRequestHeader('X-CSRF-Token', token);
}
}
});
注意:X-CSRF-Token 是 Buffalo 默认识别的请求头名,不能写成 X-XSRF-Token 或 CSRF-Token;否则服务端 CSRFProtect 中间件会拒绝请求,返回 403 Forbidden。
- 只对非 GET/HEAD 请求生效——GET 请求本身不触发 CSRF 校验,加了头也没用
- 如果用了
$.get()但误配了头,不会报错,但浪费一次 token 解析 - 在 SPA 场景下,如果页面不刷新、仅局部更新,
meta标签内容不会变,而 Buffalo 的_csrfcookie 每次会话只生成一次(除非调用context.RenewSession()),所以一般够用
Fetch 和 Axios 怎么处理 Buffalo 的 CSRF
现代 JS 不再依赖全局配置,需在每次请求中显式设置头。Fetch 更裸,Axios 可配拦截器。
Buffalo框架 1.0.1 版本源码包下载,适合需要错误处理改进、依赖更新、render.Download 注释和 request logger 调整的 v1 项目。
Fetch 示例:
const token = document.querySelector('meta[name="csrf-token"]')?.getAttribute('content');
fetch('/api/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-Token': token || ''
},
body: JSON.stringify({ name: 'alice' })
});
Axios 推荐用请求拦截器复用逻辑:
axios.interceptors.request.use(config => {
const token = document.querySelector('meta[name="csrf-token"]')?.getAttribute('content');
if (['POST', 'PUT', 'DELETE', 'PATCH'].includes(config.method?.toUpperCase())) {
config.headers['X-CSRF-Token'] = token || '';
}
return config;
});
- Buffalo 的 CSRF 中间件只检查
X-CSRF-Token头,不看 cookie 或 body 字段,所以别往body里塞_csrf=xxx - 如果后端关闭了 CSRF(
app.Use(csrf.New(...))被注释或跳过),AJAX 就不需要传——但生产环境不建议关 - 遇到
403 Forbidden: invalid csrf token,先确认meta标签是否存在且 content 非空,再查浏览器 Network 面板里请求头是否真带了X-CSRF-Token
为什么 POST 表单能自动工作,AJAX 却总 403
因为 Buffalo 的 form_for 辅助函数(或 csrf_tag())会在生成的 HTML 表单里自动插入一个隐藏字段:<input name="_csrf" type="hidden" value="xxx">,浏览器提交表单时自动带上。AJAX 完全不走这个路径,没这个“自动”环节。
- 有人试过把
_csrf当普通参数 append 到 URL 或 body,这无效——CSRF 中间件不从 query/body 解析 - 有人把 token 存在 localStorage 后反复读取,风险在于 token 泄露面扩大,且没和 session 绑定生命周期
- 真正该检查的是:HTML 是否渲染了
meta标签?JS 执行时 DOM 是否已就绪?是否在 iframe 或跨域子页面里运行导致无法访问meta?
最常被忽略的一点:Buffalo 的 CSRF token 是绑定当前 session 的,如果用户长时间没操作,session 过期,cookie 里的 _csrf 依然存在但服务端已失效——此时前端拿到的 token 是“旧的”,会稳稳地 403。需要配合 session 过期检测做重登录,而不是反复重试。

















