【问题标题】:CSRF state token does not match one provided [duplicate]CSRF 状态令牌与提供的 [重复] 不匹配
【发布时间】:2012-08-11 01:10:28
【问题描述】:

我知道 stackoverflow 上有大量关于“CSRF 状态令牌与提供的令牌不匹配”的问题。但是,我试过了,似乎并没有解决问题。你能看看我下面的代码吗?请告诉我您的想法以及如何解决问题。我已经更新到最新的 PHP SDK 版本。

<?
require_once ('src/facebook.php');
require_once ('src/fbconfig.php');

//Facebook Authentication part
$user_id = $facebook->getUser();
$loginUrl = $facebook->getLoginUrl(array(
    'scope' => 'publish_stream')
);

if ($user_id) {
    $_SESSION['user_id'] = $user_id;
    echo "<script>top.location.href = 'https://www.example.com/app-folder/welcome'</script>"; 
    exit;
} 
?>
    .
    .
<body>
<?php echo '<a href="'.$loginUrl.'" target="_top">Please login</a>'; ?>
    .
    .
</body>

【问题讨论】:

标签: php facebook facebook-graph-api


【解决方案1】:

getLoginUrl() 生成一个新令牌。如果您的用户已经登录(使用$user_id = $facebook-&gt;getUser()),您最终将获得 2 个令牌。

如果用户已经通过身份验证,则不要询问 $loginUrl。

$user_id = $facebook->getUser();

if ($user_id) {
    $_SESSION['user_id'] = $user_id;
    echo "<script>top.location.href = 'https://www.example.com/app-folder/welcome'</script>"; 
    exit;
} else {
    $loginUrl = $facebook->getLoginUrl(array(
        'scope' => 'publish_stream')
    );
}

?>

【讨论】:

  • 是的,如果用户已经通过身份验证,我上面的代码并没有要求用户再次登录。如果有用户 id,他们将引导到另一个页面,而如果没有用户 id,他们将被要求进行身份验证。
  • 我认为我的代码和你的代码之间的区别在于如果没有用户 ID,我将它与 html 代码分开
  • @Nick 我不确定我是否理解。你试过我的代码吗?有用吗?
  • 抱歉还没有。我会尝试一下。我的意思是,如果我错了,请纠正我,在 if ($user_id) 之前或之后包含 getloginurl() 不会有什么不同,因为身份验证的实际工作将在 echo $login_url 或询问用户时登录。
  • 当用户已经登录时,getuser() 有时会返回 0 或 null 吗?这会导致用户再次登录?
【解决方案2】:

我必须做到以下几点:

  1. 仅在第一页(即登录/索引)上使用PHP SDK's getLoginUrl,并将其从所有其他页面中删除。
  2. 使用FB.getLoginStatus() from the Javascript SDK and fallback to the FB.login() 或重定向到登录/索引页面
  3. 在尝试任何可能需要有效 access_token 的操作之前检查 FB.getLoginStatus()

我确信主要问题是我在每个页面上都调用了 getLoginUrl

由于我进行了这些更改,因此当机器人访问我的页面时,我只会在日志中收到“CSRF 状态令牌”错误。

【讨论】:

    【解决方案3】:

    虽然 Facebook PHP API 文档中没有说明,但您必须为 PHP 会话配置 apache 才能使登录过程正常工作。这就是我们在获取“CSRF 状态令牌与提供的令牌不匹配”时遇到的问题。

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

    这是在开发环境(使用一台服务器)中发挥作用的魅力之一,但在生产环境中却失败了。

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

    【讨论】:

      【解决方案4】:

      解决方法:
      base_facebook.php

      寻找protected function getCode()这就是问题所在。
      $this-&gt;state 变量不会为异地导航保留(自然)

      替换这个:

      if ($this->state !== null &&
      isset($_REQUEST['state']) &&
      $this->state === $_REQUEST['state']) {
      

      用这个:

      if ($_REQUEST['state'] != '' && $_REQUEST['code'] != '') {
      

      而且效果会很好

      G@bri3l

      【讨论】:

      • 那样你只是完全禁用 CSRF 保护......所以我不会认为这是解决问题的“解决方案”。
      • 当您选择 php 登录解决方案时,您会转到 facebook.com,然后再返回。你认为 $this 女巫是如何定义的,在更改域之前会保留 != '' 在转到不同的 URL 之后?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-11-09
      • 2012-02-17
      • 2012-04-07
      • 2011-11-12
      • 1970-01-01
      • 2019-02-27
      • 2016-02-13
      相关资源
      最近更新 更多