跳到主要内容

带有会话的 CSRF 示例

Github StackBlitz

一个使用跨站请求伪造 (CSRF) 中间件和会话的 GoFiber Web 应用程序示例。

本示例实现了多种 CSRF 保护的最佳实践

  • CSRF 令牌与用户会话关联。
  • 使用预会话,以便 CSRF 令牌始终可用,即使对于匿名用户也是如此(例如用于登录表单)。
  • Cookie 设置采用纵深防御方法
    • Secure: true
    • HttpOnly: true
    • SameSite: Lax
    • 过期时间:30 分钟(不活动)
    • Cookie 名称以 "__Host-" 为前缀(更多信息请参见 MDN-Set-Cookie

要求

安装 Go 模块

与任何 golang 项目一样,您需要下载并安装运行该项目所需的模块。进入 "csrf-with-session" 目录

cd csrf-with-session

然后

go mod vendor && go mod download && go mod tidy

此命令会将运行项目所需的 golang 依赖项安装到一个名为 vendor 的新目录中。

模块安装完成后,您可以像这样运行项目

go run main.go

如果一切正常,您应该看到以下内容

Server started and listening at 127.0.0.1:8443

试用演示

通过运行以下命令启动服务器

go run main.go

打开浏览器并导航到 127.0.0.1:8443

接受自签名证书警告并访问站点。

在 Chrome 中

  • 点击“高级”
  • 点击“继续前往 127.0.0.1:8443(不安全)”

在 Firefox 中

  • 点击“高级”
  • 点击“接受风险并继续”

在 Safari 中

  • 点击“显示详情”
  • 点击“访问此网站”

尝试访问 /protected 页面

使用以下测试账户之一登录

  • 用户名: user1
  • 密码: password1
  • 用户名: user2
  • 密码: password2

登录后,您将能够看到 /protected 页面。

提交 /protected 页面上的表单

登录后,您将能够看到 /protected 页面。/protected 页面包含一个提交到 /protected 页面的表单。如果您尝试在没有有效 CSRF 令牌的情况下提交表单,将会收到 403 Forbidden 错误。

CSRF 保护

除 GET、HEAD、OPTIONS 和 TRACE 之外的所有方法都会检查 CSRF 令牌。如果令牌不存在或与会话中的令牌不匹配,请求将以 403 Forbidden 错误终止。

令牌生命周期

CSRF 令牌在用户访问站点的任何页面时生成。该令牌存储在会话中,并在其过期或授权范围发生变化(例如用户登录或注销)之前有效。

重要的是 CSRF 令牌不应超出用户会话的范围,用户登录时应创建一个新会话,用户注销时应销毁会话。

CSRF 中间件有一个 SingleUseToken 配置选项,可用于为每个请求生成新的令牌。这对于某些应用程序很有用,但本示例未使用。单次使用令牌在用户打开多个标签页或使用浏览器回退按钮的场景下会影响可用性。

会话存储

本示例将会话存储在内存中,但您可以使用任何您喜欢的会话存储。更多信息请参阅 Fiber 会话文档

关于预会话的注意事项

GoFiber 的 CSRF 中间件会在会话不存在时自动创建一个会话。这意味着在使用 CSRF 中间件时,我们始终拥有预会话。在本示例中,我们在用户登录时设置一个会话变量 loggedIntrue,以区分已登录用户和未登录用户。

进一步了解

这里有一些有用的链接,您可以在其中了解更多关于此主题的信息