URL中的“state”参数与会话不匹配。

16

在 Facebook 文档中

require('include/facebook/autoload.php'); //SDK directory
$fb = new Facebook\Facebook([
'app_id' => '***********',
'app_secret' => '***********************'
]);

$helper = $fb->getRedirectLoginHelper();
$permissions = ['email', 'public_profile']; // optional
$loginUrl = $helper->getLoginUrl('http://www.meusite.com.br/login-callback.php', $permissions);

当将其导向$loginUrl时,返回结果为:Facebook SDK返回错误:跨站点请求伪造验证失败。URL和会话中的“state”参数不匹配。


2
这很可能表示PHP会话存在问题,比如会话ID没有正确传递。 - CBroe
2
这是一个与PHP会话相关的问题。我通过将<?php session_start();?>移动到页面开头解决了同样的问题。(由于某个编辑器在它之前插入了<HTML>头,所以它被向下移动了一些...)。我考虑启用php.ini中的session.auto_start = 1,但我对此还很陌生,并且想到如果其他脚本尝试启动已经启动的会话,可能会导致困扰。 - hellork
@hellork 谢谢,那就是问题所在...把session_start();放在第一行解决了。 - Partha Roy
11个回答

28

我遇到了相同的错误。

问题出现在我在 getAccessToken() 之前调用了 getLoginUrl(...)

所以,在重定向的URL和代码中去掉 getLoginUrl(...) ,就可以让代码正常运行。


这对我很有帮助!谢谢! - Wesley Brian Lachenal

17

我曾经遇到了同样的问题。对我而言,出现错误的原因是我在调用getLoginUrl(..)之前,没有在我的login.php页面的代码中加入session_start(); 以及在login-callback.php页面的顶部。

只需在你的"login"页面和"login-callback"页面中添加session_start();,就像我的现在一样,它一定会起作用。


2
是的 - Facebook 的文档从未提到您需要启用会话。 - besimple
太好了!非常感谢你! - Fryla- Cristian Marucci

6

出现此错误可能有两个原因:

  1. 在调用getLoginUrl之前,您没有调用session_start();
  2. 您在login-callback.php中再次执行了getLoginUrl,因此状态值重新生成并与重定向值不匹配

我只是缺少了session_start();。当我加上它时,问题就得到解决了。 - Jahanzaib Asgher
问题是在大多数情况下执行getLoginUrl。 - Mahdi Youseftabar

4
可能的解决方法:我使用以下配置设置。
在高级选项卡下启用WebAuthLogin。在WebAuthLogin设置中提供与$loginUrl相同的url;
例如,如果您使用$loginUrl为https://example.com/,请在WebAuthlogin Url中使用相同的url $loginUrl = $helper->getLoginUrl('https://example.com/', $permissions);

4
这个问题也会发生在同一页上生成两个或更多的登录链接的情况下(例如一个用于登录,另一个用于注册 - 即使它们指向相同的 URL,它们只是具有不同的标签)。
Facebook SDK 为每个新生成的 loginURL 创建/更新 $_SESSION [FBRLH_state]。因此,如果有2个生成的URL(使用 $helper->getLoginUrl()),那么 $_SESSION [FBRLH_state] 就会被重写2次,并且仅对最后一个生成的URL有效。先前的登录 URL 变得无效。这意味着无法生成2个有效的 loginURLs。如果生成2个相同的 URLs,则返回第一个并避免调用 Facebook SDK 来生成第二个。

3

我曾遇到同样的问题。

这个错误的原因是因为 --->

当"$helper->getLoginUrl"被调用时,它会创建一个名为“FB_State”的会话变量,这是FB用于匹配令牌的内容。每次调用getLoginUrl时,都会创建新的状态。然后,当用户授权并重定向回来时,如果您的代码不能检测到此事件并重新运行"$helper->getLoginUrl",则会出现此错误。

解决方案 ->

  1. 优化您的编码,如果已授权,请停止再次运行"$helper->getLoginUrl"。

  2. 如果已经重新运行,则将令牌的会话变量设置为空,然后用户可以再次重新授权。

  3. 当用户尝试重新授权时,他们可以删除已授权的APP,或者您需要使用"$helper->getReRequestUrl"生成新的链接。

但是,在"$helper->getLoginUrl"或"$helper->getReRequestUrl"运行之前,令牌必须通过"getAccessToken()"被调用。

祝好运!


2
最后,我查看了FB代码,并发现问题“跨站请求伪造验证失败。缺少必需参数“state””以及类似的问题是由PHP变量$_SESSION ['FBRLH_state']引起的,这个变量在FB调用登录回调文件时出现了一些“奇怪”的原因。
为了解决这个问题,我在调用函数$helper->getLoginUrl(...)之后存储了这个变量“FBRLH_state”。非常重要的是,只有在调用此函数之后才能执行此操作,因为在此函数内部填充了变量$ _ SESSION ['FBRLH_state']。
以下是我的login.php中代码示例:
$uri=$helper->getLoginUrl($uri, $permissions);
foreach ($_SESSION as $k=>$v) {                    
    if(strpos($k, "FBRLH_")!==FALSE) {
        if(!setcookie($k, $v)) {
            //what??
        } else {
            $_COOKIE[$k]=$v;
        }
    }
}
var_dump($_COOKIE);

在调用所有FB代码之前,在login-callback.php中:

foreach ($_COOKIE as $k=>$v) {
    if(strpos($k, "FBRLH_")!==FALSE) {
        $_SESSION[$k]=$v;
    }
}

最后,记得还要包含PHP会话的代码,这非常重要。
if(!session_id()) {
    session_start();
}
...
...
...
...
<?php session_write_close() ?>

我希望这个回复可以帮助你节省8-10小时的工作时间 :) 再见,Alex。


1

这个问题让我有些困惑,因为我需要修改 Facebook 的 src 文件中的一行:

src/Facebook/Helpers/FacebookRedirectLoginHelper.php

在函数“validateCsrf”中,类似于这样:
if ($result !== 0) {
        throw new FacebookSDKException('Cross-site request forgery validation failed. The "state" param from the URL and session do not match.');
    }

将其翻译为中文:并将其更改为:

if ($result === 0) {
        throw new FacebookSDKException('Cross-site request forgery validation failed. The "state" param from the URL and session do not match.');
    }

我不知道这是否违反了Facebook SDK的安全性,因此我真诚地接受任何解释或建议来回答这个问题。
您也可以在Facebook应用程序管理器中进行以下更改:
将您的网站和回调URL添加到您的Facebook应用程序帐户中:
setting->advanced:Valid OAuth redirect URIs

不要忘记在每个URL末尾添加斜杠(/),并在客户端OAuth设置中勾选所有4个复选框。

嗨,Ahmed,我有一个类似的问题,但是出现了以下错误:- Facebook SDK返回了一个错误:跨站点请求伪造验证失败。需要参数“state”缺失。我尝试了你上面的建议,但没有运气。如果我var-dump $ _GET,我可以看到“code”和“state”代码,但如果我var_dump $ _SESSION,两者都不会返回? - Tatters
2
这不是问题的解决方法,而只是_否定_了这个安全功能的本意。你应该调查问题,找到真正的原因(正如我已经评论过的,在大多数情况下,这是 PHP 会话的问题)。 - CBroe

1

我遇到了同样的错误。您是在使用1个文件还是2个文件?我一开始尝试只使用1个文件,但当我将其拆分为login.php和fb-callback.php时,根据文档建议解决了我的错误。我的会话一直被重写,因此状态从未正确保存。

祝您好运!


0

当会话缺少必要的变量时会发生这种情况。可能由几个原因引起。 在我的情况下,我在回调URL中漏掉了“www”。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接