CSRF状态令牌与提供的FB PHP SDK 3.1.1 Oauth 2.0不匹配



我的服务器日志显示"CSRF状态令牌与提供的状态令牌不匹配"错误,这似乎几乎每个用户都会发生。然而,用户已经创建和/或验证,我可以检索用户信息。我使用的是带有Apache的Linux服务器。我也在使用最新的Facebook PHP SDK v.3.1.1。有人能告诉我为什么会发生这种情况以及如何修复吗?

上周我遇到了类似的问题,并跟踪到state字段被多次调用getLoginUrl()覆盖。每次调用getLoginUrl()时,SDK中都会生成一个新的state令牌,并将其存储在$_SESSION中(这只是一个随机值),因此,如果您调用两次,并且用户使用第一个链接登录,则第二次调用将重置SDK的内部state令牌,您将在日志中收到此错误。

在Facebook授权用户并将其重定向回您的网站后,SDK会在返回的URL中查找相同的state令牌,如果不匹配,它将记录此错误(这里是源链接)。

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;
}

更清楚地说,如果调用两次,不会声明无效令牌。

要明确的是,函数可以在同一个url处理程序上调用两次,例如:

$facebook->getUser();,然后在同一个处理程序$facebook->getLogoutUrl()中,getCode()被调用两次,从而导致无效的错误消息

好吧,我曾经遇到过一次这个确切的问题,我的state&URL中的code参数-我的.htaccess文件没有转发它们。

我猜你也有同样的问题。

CSRF状态令牌与提供的不匹配

希望这能帮助

为了给chesles的答案增加一点,如果你像我一样使用session_start()-session_write_close()函数,就会出现这个问题。

如果在请求loginUrl时没有启动会话,则会出现此错误。

旁注:为什么要停止会话?

使用会话的脚本会相互停止,因为它们正在等待会话数组可用。

想象一下,您有一个拥有数千用户的流行应用程序,并且有一个发布图片的操作(php脚本)。类似这样的东西:

--在脚本的顶部启动会话

--连接到facebook

--创建图像

--与调用的api共享图像

--脚本结束,会话自动关闭

如果这样做,该会话将被脚本无故长时间使用。使用这样的脚本要小心,请使用以下内容:

--在创建facebook对象之前开始会话

--连接到facebook

--使用session_write_close()关闭会话,会话数组可用,其他脚本可以加载

--创建图像

--使用api调用共享图像/*它认为这不需要会话。*/

--脚本结束,会话已手动关闭。

干杯。

另一个注意事项-尽管Facebook PHP API文档中没有说明,但您必须为PHP会话配置apache,登录过程才能正常工作。这就是我们在获取"CSRF状态令牌与提供的状态令牌不匹配"时遇到的问题。

如果您使用的是服务器池,请确保已将其设置为使用memcache获取会话信息,否则apache将在本地写入会话信息,如果下一个请求没有发送到同一服务器,则会得到"CSRF状态令牌与提供的状态令牌不匹配"。

这是一种在开发环境(只有一台服务器)中很有魅力但在生产中失败的东西。

我们还必须重新配置CDN设置,以确保通过PHP会话cookie。

我也遇到了同样的问题。这很容易。不要拨打

$fbLoginUrl = $facebook->getLoginUrl(...);

之前

$fbUser = $facebook->getUser();

否则您将得到"CSRF状态令牌与所提供的不匹配"错误。

我在本地机器中遇到了同样的问题,问题是我的主机文件阻止了与Verisign的通信,因此Facebook试图与之通信的URL(http://crl.verisign.com/pca3.crl)从未工作过(状态:404)。

从我的主机文件中注释出各种Verisign IP地址就成功了!

CSRF状态和代码是使用本地会话检查的,我敢打赌你需要在php.ini中检查你的session.save_handler,以及它是否正常工作。

如果您在页面上使用.htaccess mod rewrite重定向,请使用行末的[QSA](查询字符串附加)来保留GET变量,否则您将丢失$code变量,这是facebook登录所必需的

最新更新