【发布时间】:2017-05-09 17:14:40
【问题描述】:
我们构建了一个 SaaS 平台,允许用户创建消息并通过预先确定的字母数字代码在任何广告媒体上共享该消息。
我们所有的表单都使用 CSRF 令牌,但我发现了一个问题。如果用户正在编辑他们的消息,然后休息一下,然后回来完成编辑并点击保存,他们将面临“CSRF 不匹配”警告消息。这是一个关键问题,因为他们必须刷新页面,丢失更改,才能重新生成有效令牌。
实际情况是初始 CSRF 令牌是基于文件名和 php_uname() 等静态参数生成的,但它也是通过 session_id() 生成的。因此,如果 session_id 发生变化,则会生成一个新的 CSRF 令牌,并且显然与旧令牌不匹配,从而导致警告消息。
在需要用户身份验证的表单上禁用 CSRF 保护很容易,但是我们有一些不需要身份验证的表单,例如用户登录。诚然,在用户登录时显示“CSRF 不匹配”并不是什么大问题,但对于不知道这意味着什么的用户来说,这看起来确实很奇怪,最终会“搞砸”并离开网站。
所以我正在寻找一种替代解决方案,以保持某种形式的保护,而不会产生毫无价值的警告消息。
两种可能的解决方案...
1) 不是基于 session_id 生成 CSRF,而是基于一些 cookie 值生成它,这将允许优雅的跨会话处理。
2) 完全放弃 CSRF。相反,验证所有表单帖子的 REFERER,如果它们与父域匹配,则继续。这将确保其他网站不会发布到我们的表单(CSRF 的主要目的)。我们实际上将这个解决方案用于我们的 ajax 请求。
我们倾向于选项 #2,但想看看是否有其他优雅的解决方案需要考虑。
【问题讨论】:
-
不要使用REFERER,容易恶搞,不可信。
-
@AlexHowansky:说得好,注意到了。