CSRF 状态令牌与提供的 FB PHP SDK 3.1.1 Oauth 2.0 不匹配
Posted
技术标签:
【中文标题】CSRF 状态令牌与提供的 FB PHP SDK 3.1.1 Oauth 2.0 不匹配【英文标题】:CSRF state token does not match one provided FB PHP SDK 3.1.1 Oauth 2.0 【发布时间】:2012-02-17 03:34:28 【问题描述】:我的服务器日志显示“CSRF 状态令牌与提供的令牌不匹配”错误,这似乎发生在几乎每个用户身上。但是,用户已创建和/或经过身份验证,我能够检索用户信息。我正在使用带有 Apache 的 Linux 服务器。我也在使用最新的 Facebook php SDK v.3.1.1 谁能告诉我为什么会这样以及如何解决它?
【问题讨论】:
我还想补充一点,这种情况最近也开始发生在我身上。用户可以按预期使用该应用程序,但是我的见解在 2 月 14 日之后突然停止报告。通过我的日志,我看到了与您遇到的完全相同的错误。 【参考方案1】:上周我遇到了类似的问题,并追踪到 state
字段被多次调用 getLoginUrl()
覆盖。每次调用getLoginUrl()
,SDK中都会生成一个新的state
令牌,并存储在$_SESSION
中(只是一个随机值),所以如果调用两次,用户使用第一个链接登录,第二次调用将重置 SDK 的内部 state
令牌,您将在日志中看到此错误。
SDK 在 Facebook 授权用户并将其重定向回您的网站后返回的 URL 中查找相同的 state
令牌,如果不匹配,它将记录此错误(这里是指向 @ 987654321@).
【讨论】:
@Jakub Facebook 出于某种原因移动了存储库...更新了链接。我不再是 PHP SDK 的活跃用户,所以我不知道这是否仍然是一个问题。希望它对你有所帮助。 @chesles 还是个大问题,马上就遇到了! @chesles 请看我的回答 @JimmyKane 我在这里没有看到你的消息……是在另一个问题上吗?另外,我在找什么? @chesles 答案已被删除。检查。【参考方案2】:在同一处理程序中检查两次令牌时,Facebook SDK 代码存在错误。
我这样编辑facebook.php
的getCode函数:
protected function getCode()
if (!isset($_REQUEST['code']) || !isset($_REQUEST['state']) || $this->state === null)
return false;
if ($this->state === $_REQUEST['state'])
// CSRF state has done its job, so clear it
$this->state = null;
$this->clearPersistentData('state');
return $_REQUEST['code'];
self::errorLog('CSRF state token does not match one provided.');
return false;
为了更清楚,如果调用两次,则不会声明无效令牌。
需要明确的是,如果例如:
$facebook->getUser();
然后在同一个处理程序 $facebook->getLogoutUrl()
然后 getCode()
被调用两次,从而导致错误消息无效
【讨论】:
如果有人想合并它,还有一个拉取请求可以解决这个问题:github.com/facebook/facebook-php-sdk/pull/122 作为第二条评论保留此代码。虽然 fb repo 中的合并再次被覆盖,但还有另一个提交被拒绝【参考方案3】:好吧,我曾经遇到过这个确切的问题,我遇到了 URL 中的 state
和 code
参数的问题 - 我的 .htaccess
文件没有转发它们。
我猜你也有同样的问题。
CSRF state token does not match one provided
希望对你有帮助
【讨论】:
@codecowboy 这个问题的具体解决方法取决于你的重写规则。主要是,确保您传递查询字符串参数。【参考方案4】:在 chesles 的回答中添加一点,如果您像我一样使用 session_start() - session_write_close() 函数,则可能会出现此问题。
如果在您请求 loginUrl 时没有启动会话,您将收到此错误。
旁注:为什么要停止会话?
使用会话的脚本会相互停止,因为它们正在等待会话数组可供使用。
假设您有一个流行的应用程序,有成千上万的用户,并且有一个动作(一个 php 脚本),您可以在其中发布图片。 像这样的:
--在脚本顶部开始会话
--连接脸书
--创建图像
--通过api调用共享图片
--脚本结束,会话自动关闭
这样做,会话将被脚本无缘无故地使用很长时间。 小心此类脚本,请改用以下内容:
--在创建 facebook 对象之前开始会话
--连接脸书
--用 session_write_close() 关闭会话,会话数组可用,其他脚本可以加载
--创建图像
--通过 api 调用共享图像 /* 它认为这不需要会话。 */
--脚本结束,会话已经手动关闭。
干杯。
【讨论】:
【参考方案5】:还有一个注意事项 - 尽管 Facebook PHP API 文档中没有说明,但您必须为 PHP 会话配置 apache 才能使登录过程正常工作。这就是我们在获得“CSRF 状态令牌与提供的令牌不匹配”时遇到的问题。
确保您使用的服务器池已设置为使用 memcache 获取会话信息,否则 apache 将在本地写入会话信息,如果下一个请求没有发送到同一台服务器,您将获得“CSRF 状态令牌与提供的不匹配”。
这是在开发环境(使用一台服务器)中发挥作用的魅力之一,但在生产环境中却失败了。
我们还必须重新配置 CDN 设置以确保我们通过 PHP 会话 cookie。
【讨论】:
【参考方案6】:我有同样的问题。这很容易。不要打电话
$fbLoginUrl = $facebook->getLoginUrl(...);
之前
$fbUser = $facebook->getUser();
否则您将收到“CSRF 状态令牌与提供的一个不匹配”错误。
【讨论】:
【参考方案7】:我在本地机器上遇到了同样的问题,问题原来是我的 hosts 文件 阻止了与 Verisign 的通信,因此 Facebook 尝试与之通信的 URL (http://crl.verisign.com/pca3.crl) 从来没有工作(状态:404)。
从我的 hosts 文件中注释掉各种 Verisign IP 地址就可以了!
【讨论】:
【参考方案8】:使用本地会话检查 CSRF 状态和代码,我打赌您需要检查 php.ini 中的 session.save_handler,以及它是否正常工作。
【讨论】:
【参考方案9】:如果您在页面上使用 .htaccess mod rewrite 重定向,请在行尾使用 [QSA](查询字符串附加)来保留 GET 变量,否则您会丢失 $code 变量,这是必需的脸书登录
【讨论】:
以上是关于CSRF 状态令牌与提供的 FB PHP SDK 3.1.1 Oauth 2.0 不匹配的主要内容,如果未能解决你的问题,请参考以下文章
FB PHP SDK 将未读消息状态更改为已读和计数未读消息
使用 php sdk 在 facebook 中获取访问令牌时出错