【发布时间】:2011-09-07 18:31:23
【问题描述】:
我已经搜索了 StackOverflow,甚至在没有帮助的情况下向 facebook 提交了一个错误。我花了整整 40 多个小时来确定这一点。我相信这是 FB.INIT 和 PHP 访问令牌之间的冲突,当服务器有大量的 .htaccess Mod Rewrites 以将 url 更改为有效的查询字符串时。我把它写成一个错误,但 Facebook 认为这是一个用户问题。我什至在他们的答案中使用了代码,但它仍然存在错误。
这是原来的问题。 在我的测试站点上,我可以让 PHP SDK 和 JS SDK 正常工作。两个都 允许登录并和谐地相互交流。没问题 在浏览页面或执行我将要更新客户端的所有功能时 和。
现在我正在尝试将更新后的新 OAuth 安装到我的客户站点中 .htaccess mod 重写。我的测试站点没有 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=')。这行得通。所以现在我的网站与 Facebook 合作 通过主宰PHP,以JS为辅。
当前问题:如果用户访问该站点但未登录标准 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 并让它们成为主宰以强制另一个的 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);
}
}
希望这会有所帮助。
【问题讨论】:
-
这也适用于 PHP 3.1.1 SDK
-
这帮助我更好地理解了如何去做!使用 fb js sdk 访问令牌通过 javascript 创建 cookie 并在 fb php sdk 中检索它肯定有效
标签: php facebook facebook-javascript-sdk facebook-php-sdk facebook-authentication