使用chi、nosurf时表单提交出现Bad Request的原因排查
问题原因分析
1. 首次GET请求能正常显示Token的逻辑
你直接渲染main.page.gohtml时,处理器已经把通过nosurf.Token(r)获取的有效Token传入了模板上下文,模板里的{{.CSRFToken}}能直接读取并渲染到表单中,所以能看到正确的Token值。但此时渲染的只是HTML片段(没有完整的<html>、<head>、<body>结构),浏览器不会正确处理响应头中的Set-Cookie字段——而nosurf的CSRF验证必须依赖这个cookie关联用户会话。
2. POST请求触发"bad request"的核心原因
nosurf的CSRF验证有两个必要条件:
- 请求参数里的
csrf_token必须和当前请求上下文的Token一致; - 请求必须携带nosurf设置的CSRF cookie,证明请求来自合法会话。
第一次GET请求时,因为响应是不完整的HTML片段,浏览器没有保存nosurf设置的cookie。POST请求提交时,nosurf收不到对应的cookie,直接判定为非法请求,返回"bad request"。
3. 添加{{template "base" .}}后解决问题的原因
引用base模板后,渲染出的是完整的HTML页面(包含标准文档结构),浏览器会正常处理响应头中的Set-Cookie,保存好nosurf的CSRF cookie。当你提交POST请求时,nosurf能同时验证参数中的Token和cookie中的会话信息,验证通过后请求即可正常处理。
总结来说:
- 无base模板时,GET请求能渲染Token,但浏览器没存关键cookie,POST请求缺验证依据;
- 有base模板时,完整HTML触发浏览器保存cookie,POST请求满足nosurf的双重验证要求。
内容的提问来源于stack exchange,提问作者AnonymFromInternet
相关产品推荐
相关产品推荐

