3

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

这是原始问题。在我的测试站点上,我可以让 PHP SDK 和 JS SDK 正常工作。两者都允许登录并相互协调工作。在浏览页面或执行我将要更新客户端的所有功能时没有问题。

现在我正在尝试将更新的新 OAuth 安装到我的客户站点中,并使用大量的 .htaccess mod Rewrites。我的测试站点没有 Mod ReWrites。

起初你可以用 PHP 登录就好了。但是,一旦您转到站点内的另一个页面,您就会丢失访问令牌,并出现常见错误:必须使用活动访问令牌来查询有关当前用户的信息。

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

所以为了解决这个问题,我必须将 PHP 的访问令牌传递给 SESSION 并将其放在我的 api 调用中。就像这样,FB.api('/me/?access_token=')。这行得通。所以现在我的网站通过以 JS 为辅助的主宰 PHP 与 Facebook 合作。

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

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

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

我的结论:基于 JS 的感知 URL 和 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 并让它们成为主宰以强制另一个的 Access Token。这是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);

        }
}

希望这可以帮助。

4

1 回答 1

0

如果它在没有 mod 重写但没有 mod rewrites 的情况下工作,那么这就是问题所在,

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

于 2011-09-07T20:16:27.383 回答