1

我正在使用 Facebook 的服务器端用户身份验证来尝试让人们登录到我们的网站。为了防止 CSRF,Facebook 建议创建一个随机会话状态变量,将其传递给 FB,然后 FB 将其传回以比较值以确保没有安全问题。这似乎在除 Firefox 之外的所有浏览器中都能正常工作。Firefox 正在发送状态变量,但在返回站点时不会存储它。session_start() 出现在文档的顶部,因为出于安全原因,我删除了一些变量和其他代码,所以下面没有引用它。

if(empty($code)) {
    $rand = md5(uniqid(rand(), TRUE)); // CSRF protection
    $_SESSION['mbny_state'] = $rand;
    $dialog_url = "https://www.facebook.com/dialog/oauth?client_id="
        . $app_id . "&redirect_uri=" . urlencode($my_url) . "&state="
        . $_SESSION['mbny_state'] . "&scope=publish_stream,user_birthday,user_hometown,email";
    header('Location: ' . $dialog_url);
}

$state = $_REQUEST['state'];
$secret_state = $_SESSION['state'];

// Check session state to prevent hacking
if($secret_state == $state) {
    $token_url = "https://graph.facebook.com/oauth/access_token?"
        . "client_id=" . $app_id . "&redirect_uri=" . urlencode($my_url)
        . "&client_secret=" . $app_secret . "&code=" . $code;

    $response = file_get_contents($token_url);
    $params = null;
    parse_str($response, $params);

    // store the access token for future requests
    $_SESSION['access_token'] = $params['access_token'];

    // define graph url allowing us to communicate with FB with user's account
    $graph_url = "https://graph.facebook.com/me?access_token="
        . $params['access_token'];

    $user = json_decode(file_get_contents($graph_url));
}
else {
    $error_message = 'An error has occurred. Your session ID does not match. Please exit and try again.<br /><br />' . $secret_state . ' :: ' . $state . ' :: ' . $_SESSION['test'];
}

Firefox 会显示错误消息。我在文档后面返回了 $_SESSION['state'] 的值,它即将变为 NULL。

此外,我在会话中添加了一个名为 test 的测试变量,它被 Firefox 很好地存储了。我错过了什么?

提前致谢。

编辑:似乎 Firefox 愿意在 if 语句之外存储会话变量。如果我在 if 语句之前设置 $_SESSION['myny_state'] ,它会在 FB 以 $code 返回时存储该值。这里的问题是状态肯定不匹配,因为它在每次页面调用时都会被重置,因为它在 if 语句之外。

我们说话的时候我正在掉头发。

4

4 回答 4

4

在对 Firefox 内部发生的事情进行了非常密切的关注后,我注意到 Firefox 正在从域名中删除“www”,即使该地址最初包含“www”。然后会话被保存到http://domain.com/whatever,而 Facebook 应用程序将用户重定向回http://www.domain.com/whatever

有两种方法可以解决这个问题。我选择使用 .htaccess 重写条件来解决这个问题:

RewriteEngine on
RewriteCond %{HTTP_HOST} ^domain.com [NC]
RewriteRule ^(.*)$ http://www.domain.com/$1 [L,R=301]

这也可以通过如下设置 session.cookie_domain 来实现:

ini_set('session.cookie_domain', '.domain.com');

希望有人觉得这很有用。也许它会为您节省五个小时的调试时间,而这些东西实际上是没有错误的。

附带说明一下,强制您的网站使用 www 或不使用 www 被认为是良好的 SEO 实践 - 而不是两者兼而有之。

于 2012-11-19T21:16:34.487 回答
3

$_SESSIONvars 存储在服务器端,而不是客户端。

  1. 你在哪里打电话session_start()?因为它不在您引用的代码中。
  2. 您的浏览器中是否禁用了 cookie?IIRC PHP 通常设置一个 cookiePHPSESSID来将客户端浏览器与服务器的会话数据连接起来。

重新编辑

Facebook 可能会删除您的状态变量,因为它没有进行 urlencoded。尝试更换:

urlencode($my_url) . "&state=" . $_SESSION['state']

和:

urlencode($my_url . "&state=" . $_SESSION['state'])
于 2012-11-19T17:19:07.143 回答
1

如果这是您的完整代码,则必须session_start();在顶部或开始使用 Session 变量之前添加。

此外,您需要session_start();在要添加/检索数据的所有页面上添加。

于 2012-11-19T17:18:49.000 回答
0

有时重启你的火狐浏览器可以解决问题。我不知道为什么,但它有效。

于 2015-02-24T06:03:43.223 回答