如何从offline_access弃用以来扩展访问令牌的有效性

由于在Facebook的身份validationstream程中已不再使用offline_access 权限 ,因此我们在没有该权限的情况下出现了所谓的长时间访问令牌的问题。

在Facebook关于弃用的文件中说,服务器端OAuth生成的访问令牌将会长期存在,但事实并非如此。

我错过了什么吗? 在应用程序设置的一些设置 我需要使用一些特殊的代码来延长访问令牌的到期时间? 据我了解的文档,对于服务器端身份validation,访问令牌可以访问PHP SDK的getAccessToken()方法,当用户login是长期居住。

编辑(2012年8月14日):
一个星期前官方的Facebook PHP SDK已经更新。 函数名称已更改为setExtendedAccessToken ,并决定事后需要销毁会话,以消除有两个活动会话的风险。
此外,该函数不再实际返回该标记,而是将其存储在持久性数据中。 之后您可以使用公共函数getAccessToken获取新的访问令牌。 从官方的Facebook PHP SDK github页面抓取新的SDK,以确保你是最新的。

原始答案:

我已经添加了一个新的公共函数base_facebook.php文件,它返回一个新的访问令牌,在60天后过期。 收到正常访问令牌后,可以向此function发出请求。 我还没有testing,但我认为你还需要在开发者应用程序的高级设置中启用“deprecate offline_access”。

只需将其添加到Facebook类中的base_facebook.php中,并调用它即可。 它适用于我。

  public function getExtendedAccessToken(){ try { // need to circumvent json_decode by calling _oauthRequest // directly, since response isn't JSON format. $access_token_response = $this->_oauthRequest( $this->getUrl('graph', '/oauth/access_token'), array( 'client_id' => $this->getAppId(), 'client_secret' => $this->getAppSecret(), 'grant_type'=>'fb_exchange_token', 'fb_exchange_token'=>$this->getAccessToken() ) ); } catch (FacebookApiException $e) { // most likely that user very recently revoked authorization. // In any event, we don't have an access token, so say so. return false; } if (empty($access_token_response)) { return false; } $response_params = array(); parse_str($access_token_response, $response_params); if (!isset($response_params['access_token'])) { return false; } return $response_params['access_token']; } 

其实说的是:

如果access_token是从服务器端OAuth调用生成的,则生成的access_token 将具有较长的到期时间 。 如果在该用户仍然存在有效的access_token的情况下进行呼叫,则从第二次呼叫返回的access_token将保持不变,只有到期时间将被延长。 再次,在同一天内多次调用这将导致只有第一次通话延长到期时间。

这意味着它只会比客户端生成的令牌更长,并且要接收扩展令牌(60天),则需要通过发出请求来手动执行:

 https://graph.facebook.com/oauth/access_token? client_id=APP_ID& client_secret=APP_SECRET& grant_type=fb_exchange_token& fb_exchange_token=EXISTING_ACCESS_TOKEN 

此令牌仍可能由于以下几个原因而失效,以及如何处理如何处理过期访问令牌博客post。

更新:
截至2012年8月7日,您可以使用setExtendedAccessToken方法来扩展access_token而不是手动构buildURL并检索详细信息。

/ /使用JavaScript的popup窗口的Facebooklogin

 FB.login(function(response) { if (response.authResponse) { var accessToken = response.authResponse.accessToken; 

//获得1-2小时到期时间

//获取了一个名为facebook控制器的控制器

  $request = $this->getRequest(); $params = $request->getParams(); $token=$params['accessToken']; 

//将访问令牌延长至60天

  $conf = $this->getConfigs(); $appid = $conf['fbdetails']['appid']; $secret = $conf['fbdetails']['secret']; $baseurl = $conf['app']['baseurl']; 

//执行下面的代码之后,我们会有一个响应,使用令牌过期时间为60天。

  $token_url = "https://graph.facebook.com/oauth/access_token?client_id=".$appid."&client_secret=".$secret."&grant_type=fb_exchange_token&fb_exchange_token=".$token; 

//上面的响应给出了parsing。

  $c = curl_init(); curl_setopt($c, CURLOPT_RETURNTRANSFER, 1); curl_setopt($c, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($c, CURLOPT_URL, $token_url); $contents = curl_exec($c); $err = curl_getinfo($c,CURLINFO_HTTP_CODE); curl_close($c); $paramsfb = null; parse_str($contents, $paramsfb); 

//在parsing上述执行代码中的内容之后,存储新的扩展访问权限。

  $user_session = new Zend_Session_Namespace('fbuser'); $user_session->access_token = $paramsfb['access_token']; 

//存储到会话。

  $this->_redirect('/home'); 

//有一个很好的编码

通过服务器端OAuth调用生成的访问令牌将是扩展(更长)types,您不需要交换它。 它已经是一个扩展令牌。 您唯一要做的就是在您的应用设置中启用“弃用离线访问”。 这当然只有当“弃用离线访问”先前被禁用时才是必需的。

然后,当您通过Facebook对用户进行身份validation时,您将收到一个长达60天的访问令牌。 在同一天进行多次validation只会导致第一次validation延长到期时间。

如果您需要永不过期的访问令牌,请参阅我的答案

从开发者页面:

通过使用长期的用户访问令牌,查询[用户ID] /帐户端点现在将为用户pipe理的页面提供不会过期的页面访问令牌

这是为了将页面访问令牌扩展到永不过期,并且延长在2个月后过期的用户访问令牌(“新访问令牌”)的寿命。

好吧,所以花了大概一个星期的研究,但这是我的解决scheme。 在https://developers.facebook.com/tools/explorer/确保你有manage_page作为你的access_token的一部分。; 之后,使用此代码与您的应用程序ID,秘密,并redirect:

 <?php app_id = "APP_ID"; $app_secret = "APP_SECERET"; $post_login_url = "REDIRECT_URL"; $code = $_REQUEST['code']; //Obtain the access_token with publish_stream permission if(empty($code)){ $dialog_url= "http://www.facebook.com/dialog/oauth?" . "client_id=" . $app_id . "&redirect_uri=" . urlencode( $post_login_url) . "&COMMA_SEPARATED_LIST_OF_PERMISSION_NAMES"; echo("<script>top.location.href='" . $dialog_url . "'</script>"); } else { $token_url="https://graph.facebook.com/oauth/access_token?" . "client_id=" . $app_id . "&redirect_uri=". urlencode($post_login_url) . "&client_secret=" . $app_secret . "&code=" . $code; $response = file_get_contents($token_url); $params = null; parse_str($response, $params); $access_token = $params['access_token']; echo 'access token: ' . $access_token.'<br>'; if($access_token){ $token_url="https://graph.facebook.com/oauth/access_token?" . "client_id=" . $app_id . "&redirect_uri=". urlencode($post_login_url) . "&client_secret=" . $app_secret .'&grant_type=fb_exchange_token' . "&fb_exchange_token=" . $access_token; $response = file_get_contents($token_url); $access_token = $params['access_token']; echo 'new access token: '.$access_token; } }*/ ?> 

之后,复制“新的访问令牌”,然后返回到https://developers.facebook.com/tools/explorer/当您在访问令牌字段中将您的新访问令牌过去。; 然后点击提交。 之后,在节点中,您将看到一个+ _ ___点击此并向下滚动到帐户,然后单击它。 find您需要访问令牌的页面,并将其复制并粘贴到访问密钥字段中。 点击debugging,你会看到它永远不会过期。 保存该令牌将保持有效,只要您不重置您的应用程序的秘密。

受到之前答案的启发,我写了一个简单的令牌自我更新程序。 首先,把你当前的标记放在'token.sec'文件中。

这个程序将从文件中读取一个令牌,如果一切正常,用新的令牌更新。 在其他程序中,您只需使用令牌:

 $access_token = file_get_contents("token.sec"); 

我们到了:

 <?php $app_id = "<your app id>"; $app_secret = "<your app secret>"; $access_token = file_get_contents("token.sec"); $token_url="https://graph.facebook.com/oauth/access_token?" . "grant_type=fb_exchange_token" . "&client_id=" . $app_id . "&client_secret=" . $app_secret . "&fb_exchange_token=" . $access_token; $ch = curl_init($token_url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $response = curl_exec($ch); if($response === false) { die ('Curl error: ' . curl_error($ch)); } // Close handle curl_close($ch); // parse the output parse_str($response, $params); if(!isset($params['access_token'])) { die("No access token"); } echo ("New token: $access_token\n"); // eveything looks OK rename("token.sec", "token.sec.back"); // just in case $myfile = fopen("token.sec", "w") or die("Unable to open file!"); fwrite($myfile, $access_token); fclose($myfile); ?> 

最后,我们可以在我们的crontab中添加这个来每月更新一次令牌:

 0 0 1 * * cd /home/<path>; php exchangeToken.php