csrf
csrf 中间件为 Flame 实例提供 CSRF 令牌的生成和验证服务,该中间件依赖于 session 中间件。
你可以在 GitHub 上阅读该中间件的源码或通过 pkg.go.dev 查看 API 文档。
下载安装
go get github.com/flamego/csrf
用法示例
注意
本小结仅展示 csrf 中间件的相关用法,示例中的用户验证方案绝不可以直接被用于生产环境。
csrf.Csrfer 可以配合 csrf.Options 对中间件进行配置,并使用 csrf.Validate 来进行 CSRF 令牌的验证:
package main
import (
	"net/http"
	"github.com/flamego/csrf"
	"github.com/flamego/flamego"
	"github.com/flamego/session"
	"github.com/flamego/template"
)
func main() {
	f := flamego.Classic()
	f.Use(template.Templater())
	f.Use(session.Sessioner())
	f.Use(csrf.Csrfer())
	// 模拟会话认证,若 userID 存在则重定向到包含 CSRF 令牌的表单页面
	f.Get("/", func(c flamego.Context, s session.Session) {
		if s.Get("userID") == nil {
			c.Redirect("/login")
			return
		}
		c.Redirect("/protected")
	})
	// 设置会话的 uid
	f.Get("/login", func(c flamego.Context, s session.Session) {
		s.Set("userID", 123)
		c.Redirect("/")
	})
	// 使用 x.Token() 将 CSRF 令牌渲染到模板中
	f.Get("/protected", func(c flamego.Context, s session.Session, x csrf.CSRF, t template.Template, data template.Data) {
		if s.Get("userID") == nil {
			c.Redirect("/login", http.StatusUnauthorized)
			return
		}
		// 传递令牌到被渲染的模板
		data["CSRFToken"] = x.Token()
		t.HTML(http.StatusOK, "protected")
	})
	// 应用 CSRF 验证
	f.Post("/protected", csrf.Validate, func(c flamego.Context, s session.Session, t template.Template) {
		if s.Get("userID") != nil {
			c.ResponseWriter().Write([]byte("You submitted with a valid CSRF token"))
			return
		}
		c.Redirect("/login", http.StatusUnauthorized)
	})
	f.Run()
}
<form action="/protected" method="POST">
  <input type="hidden" name="_csrf" value="{{.CSRFToken}}">
  <button>Submit</button>
</form>