csrf

csrf 中间件为 Flame 实例提供 CSRF 令牌的生成和验证服务,该中间件依赖于 session 中间件。

你可以在 GitHubcsrf - 图1在新窗口打开 上阅读该中间件的源码或通过 pkg.go.devcsrf - 图2在新窗口打开 查看 API 文档。

下载安装

Go 语言的最低版本要求为 1.16

  1. go get github.com/flamego/csrf

用法示例

注意

本小结仅展示 csrf 中间件的相关用法,示例中的用户验证方案绝不可以直接被用于生产环境。

csrf.Csrfercsrf - 图3在新窗口打开 可以配合 csrf.Optionscsrf - 图4在新窗口打开 对中间件进行配置,并使用 csrf.Validatecsrf - 图5在新窗口打开 来进行 CSRF 令牌的验证:

  • main.go
  • templates/protected.tmpl
  1. package main
  2. import (
  3. "net/http"
  4. "github.com/flamego/csrf"
  5. "github.com/flamego/flamego"
  6. "github.com/flamego/session"
  7. "github.com/flamego/template"
  8. )
  9. func main() {
  10. f := flamego.Classic()
  11. f.Use(template.Templater())
  12. f.Use(session.Sessioner())
  13. f.Use(csrf.Csrfer())
  14. // 模拟会话认证,若 userID 存在则重定向到包含 CSRF 令牌的表单页面
  15. f.Get("/", func(c flamego.Context, s session.Session) {
  16. if s.Get("userID") == nil {
  17. c.Redirect("/login")
  18. return
  19. }
  20. c.Redirect("/protected")
  21. })
  22. // 设置会话的 uid
  23. f.Get("/login", func(c flamego.Context, s session.Session) {
  24. s.Set("userID", 123)
  25. c.Redirect("/")
  26. })
  27. // 使用 x.Token() 将 CSRF 令牌渲染到模板中
  28. f.Get("/protected", func(c flamego.Context, s session.Session, x csrf.CSRF, t template.Template, data template.Data) {
  29. if s.Get("userID") == nil {
  30. c.Redirect("/login", http.StatusUnauthorized)
  31. return
  32. }
  33. // 传递令牌到被渲染的模板
  34. data["CSRFToken"] = x.Token()
  35. t.HTML(http.StatusOK, "protected")
  36. })
  37. // 应用 CSRF 验证
  38. f.Post("/protected", csrf.Validate, func(c flamego.Context, s session.Session, t template.Template) {
  39. if s.Get("userID") != nil {
  40. c.ResponseWriter().Write([]byte("You submitted with a valid CSRF token"))
  41. return
  42. }
  43. c.Redirect("/login", http.StatusUnauthorized)
  44. })
  45. f.Run()
  46. }
  1. <form action="/protected" method="POST">
  2. <input type="hidden" name="_csrf" value="{{.CSRFToken}}">
  3. <button>Submit</button>
  4. </form>