【问题标题】:CSRF state token does not match one provided FB PHP SDK 3.1.1 Oauth 2.0CSRF 状态令牌与提供的 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 日之后突然停止报告。通过我的日志,我看到了与您遇到的完全相同的错误。

标签: facebook facebook-graph-api facebook-php-sdk oauth-2.0 csrf


【解决方案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 中的 statecode 参数的问题 - 我的 .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 变量,这是必需的脸书登录

            【讨论】:

              猜你喜欢
              • 2013-11-09
              • 1970-01-01
              • 2012-08-11
              • 2012-04-07
              • 1970-01-01
              • 2011-11-12
              • 1970-01-01
              • 2019-02-27
              • 1970-01-01
              相关资源
              最近更新 更多