Facebook JS SDK和PHP SDK访问令牌冲突

时间:2011-09-07 18:31:24

标签: php facebook facebook-javascript-sdk facebook-php-sdk facebook-authentication

我已经搜索过StackOverflow,甚至在没有任何帮助的情况下向facebook提交了一个错误。我花了40多个小时坚持这一点。我认为它是FB.INIT和PHP访问令牌之间的冲突,当服务器有大量.htaccess时,Mod重写将URL更改为有效的查询字符串。我把它写成了一个bug,但Facebook认为这是一个用户问题。我甚至在他们的答案中使用了代码,但仍然存在问题。

这是原始问题。 在我的测试网站上,我可以使用JS SDK获得PHP SDK,以便正常工作。都 允许登录并协调工作。没问题 浏览网页或执行所有功能时,我即将更新客户端 用。

现在我正在尝试将更新的OAuth更新到我的客户端站点中 .htaccess mod重写。我的测试网站没有Mod ReWrites。

首先你可以用PHP登录就好了。但是一旦你去了另一个 网站中您丢失了Access令牌,其中包含常见错误:An 必须使用活动访问令牌来查询有关当前用户的信息。

通过检查PHP api是否失败然后使用a来解决这个问题 file_get_contents命令取自Facebook自己的授权页面 (反对:https://graph.facebook.com/oauth/access_token?)并重置 访问令牌。这很有效。但这导致FB.init失败了 响应错误:必须使用活动访问令牌来查询有关的信息 当前用户。由FB.api('/ me')回调

因此,为了解决这个问题,我必须将PHP的访问令牌传递到SESSION并放置 它在我的api电话中。像这样,FB.api('/ me /?access_token =')。这很有效。所以现在我的网站与Facebook合作 通过支配PHP,JS是次要的。

CURRENT ISSUE:如果用户访问该站点并且未登录该标准 PHP Facebook功能和使用FB JS SD的功能;该网站提示 具有该站点功能的适当权限的JS登录。用户 接受并登录。从JS的角度来看,一切都很好。该 console.log转储从页面到页面告诉我。

问题:PHP不会从设置的cookie中确认Access_token JS SDK,也不会从file_get_contents接收cookie(踢回来 HTTP请求失败400)。因此,用户通过JS登录 PHP不接受他们的登录,仍然显示PHP getLoginUrl函数。

当在PHP facebook对象上执行var_dump时,我们会看到所有字段 包含数据;代码,状态,access_token,算法等。但是当一个 $ facebook-> api('/ me')在每个页面上(上面已成功)执行 我们收到错误:必须使用活动访问令牌来查询信息 关于当前用户。

我的结论:基于感知的URL存在不匹配的代码生成 JS和PHP的实际url。在哪里强制JS进行PHP访问更容易 令人无法做到令牌,因为PHP无法让JS占主导地位。

这是每页上的PHP代码。

$app_id = 'APP_ID';
$app_secret = 'APP_SEC';
$my_url = 'http://'.$_SERVER['HTTP_HOST'];
$facebook = new Facebook(array(
  'appId'  => $app_id,
  'secret' => $app_secret,
));
$_SESSION[fbappID] = $facebook->getAppId();
$_SESSION[fbaccTok] = $facebook->getAccessToken();
$sigReq = $facebook->getSignedRequest();
$code = $sigReq[code];
$userID = $facebook->getUser();
if($userID)
{
  try {
    $user_profile = $facebook->api('/me');
  } catch (FacebookApiException $e) {
    error_log($e);
    $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);
        if($params[access_token]!="")
    {
      $facebook->setAccessToken($params[access_token]);
      $_SESSION[fbaccTok] = $facebook->getAccessToken();
    }
    try{
      $user_profile = $facebook->api('/me');
    }catch(FacebookApiException $e) {
      error_log($e);
      $userID = null;
    }
  }
}
if($userID)
{
  $user_profile = $facebook->api('/me');
  $logout =  $facebook->getLogoutUrl();
}
else
{
  $login = "<a href='".$facebook->getLoginUrl()."'>Log In with Facebook</a>";
}

使用的Javascript:

<script>
 FB.init({
  appId  : '$_SESSION[fbappID]',
status : true,
  cookie : true, 
  xfbml  : true,  
  oauth : true 
  });
  FB.api('me/permissions/?access_token=<?php print $_SESSION[fbaccTok]?
  >',function(response){console.log(response)});
</script>

答案:

以下是答案:允许Javascript成为主要入口点。你不能两者兼得。你必须选择一个,PHP或javascript,并使它们成为强制对方的访问令牌的主导。这是Javascript:

window.fbAsyncInit = function() {

  FB.init({
      appId  : '12345',
      channelURL : '/channel.php',
      status : true,
      cookie : true, // enable cookies to allow the server to access the session
      xfbml  : true,  // parse XFBML
      oauth : true //enables OAuth 2.0
    });
 FB.getLoginStatus(function(response){
    if(response.authResponse){
        FB.accessToken = ;
        createCookie('fbToken',response.authResponse.accessToken,.1);
        createCookie('fbID',response.authResponse.userID,.1);
    }
     });
 FB.Event.subscribe('auth.login', function(response) {
    createCookie('fbToken',response.authResponse.accessToken,.1);
    createCookie('fbID',response.authResponse.userID,.1);
    createCookie('fbLogin',1,30);
    window.location.reload();

 });
 FB.Event.subscribe('auth.logout', function() {
        eraseCookie('fbLogin');
         eraseCookie('fbToken');
         eraseCookie('evFB.uid');
 });
}

createCookie和eraseCookie是可以通过网络找到的cookie函数。这是粗略的代码而不是精致的。基本上我创建自己的Cookie来传递信息。由于FB JS SDK在登录和注销时刷新页面,我可以在PHP接管页面刷新之前删除并创建cookie或修改它们。

现在这里是强制JS cookie访问令牌的PHP。

require_once("/facebook.php");

$facebook = new Facebook(array(
  'appId'  => $app_id,
  'secret' => $app_secret,
));
$my_url = $facebook->returnGetUrl();
$_SESSION[fbaccTok] = (isset($_COOKIE[fbToken]))?$_COOKIE[fbToken]:$facebook->getAccessToken();


$sigReq = $facebook->getSignedRequest();
$code = ($_REQUEST[code]=='')?$sigReq[code]:$_REQUEST[code];

$GLOBALS[fbUser]= $facebook->getUser();

if(isset($_COOKIE[fbLogin]))
{
    if($_COOKIE[fbLogin]==1)
    {
        $GLOBALS[fbUser] = $facebook->getUser();
        //print $GLOBALS[fbUser];
    }
    else
    {
        $GLOBALS[fbUser] = null;
    }
}
else
{
    $GLOBALS[fbUser] = null;
}
if($GLOBALS[fbUser] && $_COOKIE[fbToken])
{
    $GLOBALS[fbArray] = array(
        'access_token' => $_COOKIE[fbToken]
        );
        try {
            $GLOBALS[fbUserProfile] = $facebook->api('/me','GET',$GLOBALS[fbArray]);
            //print_r($GLOBALS[fbUserProfile]);


        } catch (FacebookApiException $e) {
            error_log($e);

        }
}

希望这有帮助。

1 个答案:

答案 0 :(得分:0)

如果它没有mod重写但没有mod重写,那么这就是问题,

你可以做的是创建另一个facebook测试应用程序并在没有mod重写的单独服务器上托管,然后逐步添加mod重写1,直到问题发生,看看哪一个导致它。