Php 如何在脱机访问被拒绝后扩展访问令牌的有效性

Php 如何在脱机访问被拒绝后扩展访问令牌的有效性,php,facebook-graph-api,facebook-php-sdk,oauth-2.0,facebook-oauth,Php,Facebook Graph Api,Facebook Php Sdk,Oauth 2.0,Facebook Oauth,由于Facebook的流量中不推荐使用离线访问,因此我们无法在没有该许可的情况下获得所谓的长期访问令牌 在文章中说,服务器端OAuth生成的访问令牌将长期存在,但事实并非如此 我错过什么了吗?应用程序设置中的某些设置?我需要使用一些特殊代码来延长访问令牌的过期时间?据我所知,对于服务器端身份验证,当用户登录时,可以通过PHP SDK的getAccessToken()方法访问的访问令牌是长期存在的。实际上是这样说的: 如果访问令牌是从服务器端OAuth调用生成的,则生成的访问令牌将具有更长的过期时

由于Facebook的流量中不推荐使用
离线访问
,因此我们无法在没有该许可的情况下获得所谓的长期访问令牌

在文章中说,服务器端OAuth生成的访问令牌将长期存在,但事实并非如此


我错过什么了吗?应用程序设置中的某些设置?我需要使用一些特殊代码来延长访问令牌的过期时间?据我所知,对于服务器端身份验证,当用户登录时,可以通过PHP SDK的
getAccessToken()
方法访问的访问令牌是长期存在的。

实际上是这样说的:

如果访问令牌是从服务器端OAuth调用生成的,则生成的访问令牌将具有更长的过期时间。如果在该用户仍有有效访问令牌的情况下进行调用,则第二次调用返回的访问令牌将保持不变,并且仅延长到期时间。同样,在同一天内多次调用此函数只会导致第一次调用延长到期时间

这意味着它将比客户端生成的令牌稍长,要接收扩展令牌(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
这个令牌仍然会因为几个原因而变得无效,如何处理这个问题在博客文章中有描述

更新:
截至,您可以使用
setExtendedAccessToken
方法扩展
access\u token
,而不是手动构建URL和检索详细信息。

编辑(2012年8月14日):
一周前,官方Facebook PHP SDK进行了更新。函数名已更改为setExtendedAccessToken,并决定我们实际上需要在之后销毁会话,以消除有两个活动会话的风险。
此外,函数不再实际返回令牌,而是将其存储在持久数据中。因此,您可以在以后使用公共函数getAccessToken获取新的访问令牌。从获取新SDK以确保您是最新的

原始答案:

我在base_facebook.php文件中添加了一个新的公共函数,它返回一个新的访问令牌,该令牌将在60天后过期。您可以在收到正常访问令牌后请求此函数。我还没有测试,但我假设您还需要在开发人员应用程序的高级设置中启用“不推荐脱机访问”

只需将此添加到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'];
}

//使用javascript作为facebook登录的弹出窗口

FB.login(function(response) {

            if (response.authResponse) {

                   var accessToken = response.authResponse.accessToken;
//已获取过期时间为1-2小时的accesstoken

//将accesstoken放入名为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'];
//在执行下面的代码之后,我们将得到一个带有acess令牌的响应,过期时间为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;
//上面给出的响应用于解析

        $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);
//解析上述执行代码中的内容后,将存储新的扩展accesstoken

        $user_session = new Zend_Session_Namespace('fbuser');
        $user_session->access_token = $paramsfb['access_token'];
//存储到会话

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

//有一个好的编码

通过服务器端OAuth调用生成的访问令牌将是扩展(更长)类型,您不需要交换它。它已经是一个扩展令牌。 您必须做的唯一一件事是在应用程序设置中启用“不推荐脱机访问”。当然,只有在以前禁用了“不推荐脱机访问”的情况下,才需要这样做


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

如果您需要一个页面的永不过期的访问令牌,请参阅我的an回答类似的问题

从开发者页面:

通过使用长寿命用户访问令牌,查询[用户] ID]/accounts端点现在将提供页面访问令牌不提供 用户管理的页面过期


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

好吧,这花了大约一周的时间进行研究,但我的解决方案是这样的。 在中,确保您已将manage_页面作为access_令牌的一部分。然后将此代码与您的应用程序id、密码和重定向一起使用:

<?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;

        }
    }*/

?>

受前面答案的启发,我编写了一个简单的令牌自我更新程序。首先,将当前令牌放入“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
01**cd/home/;php-exchangeToken.php

在我的例子中,我不得不将“getAppSecret()”替换为“getApiSecret()”(SDK版本3.1.1)getApiSecret函数不是在SDK 3.1.1中只返回getAppSecret函数吗?getApiSecret函数已贬值,并将在未来版本中删除?有人能告诉我这是否适用于使用签名请求方法获得的访问令牌吗?因为facebook文档似乎说它仅用于客户端流?Boyes,它现在工作了吗?我尝试了,但得到的错误如下:要检查您的访问权,请将字符串复制并粘贴到:…您希望看到类似“Expires:1347718933(大约2个月内)”的内容。如果您看到类似“Expires:1342540800(大约一小时内)”的内容“那么您还没有扩展访问令牌。比较getAccessToken()与此答案getExtendedAccessToken()的结果。祝你好运我也经历过这种行为。事实上,打电话给