通常使用以下方法之一来防止跨站请求伪造 (CSRF):
- 检查referer - RESTful 但不可靠
- 将令牌插入表单并将令牌存储在服务器会话中 - 不是真正的 RESTful
- 神秘的一次性 URI - 不是 RESTful,原因与令牌相同
- 为此请求手动发送密码(不是用于 HTTP auth 的缓存密码)- RESTful 但不方便
我的想法是使用用户密码、神秘但静态的表单 ID 和 JavaScript 来生成令牌。
<form method="POST" action="/someresource" id="7099879082361234103">
<input type="hidden" name="token" value="generateToken(...)">
...
</form>
GET /usersecret/john_doe
由 JavaScript 从经过身份验证的用户那里获取。- 回应:
OK 89070135420357234586534346
这个秘密在概念上是静态的,但可以每天/每小时更改......以提高安全性。这是唯一保密的事情。 - 使用 JavaScript 读取神秘的(但对所有用户都是静态的!)表单 ID,将其与用户密码一起处理:
generateToken(7099879082361234103, 89070135420357234586534346)
- 将表单连同生成的令牌一起发送到服务器。
- 由于服务器知道用户密码和表单 id,因此可以在发送之前运行与客户端相同的 generateToken 函数并比较两个结果。只有当两个值相等时,才会授权该操作。
这种方法有问题吗,尽管没有 JavaScript 就无法工作?
附录: