简体   繁体   English

Facebook SDK访问令牌和Ajax

[英]Facebook SDK access tokens and ajax

I followed the Facebook SDK for PHP docs and created two files, login.php and fb-callback.php, with all the lookup logic in fb-callback.php. 我遵循了PHP文档的Facebook SDK,并创建了两个文件login.php和fb-callback.php,并将所有查找逻辑包含在fb-callback.php中。 When I do this, everything works fine. 当我这样做时,一切正常。

But I want to move the lookup logic to get-posts.php and call it via ajax from fb-callback.php. 但是我想将查找逻辑移到get-posts.php并通过abx从fb-callback.php调用它。 When I do so, I can't seem to get the access token. 这样做时,我似乎无法获得访问令牌。 I get the error noted below, "Access Token: Bad request". 我收到下面指出的错误,“访问令牌:错误的请求”。

I have registered both fb-config.php and get-posts.php as Valid OAuth Redirect URIs. 我已经将fb-config.php和get-posts.php注册为有效的OAuth重定向URI。 So how do I get the proper parameters to get-posts.php? 那么,如何获取get-posts.php的适当参数?

Here are all the associated files: 以下是所有相关文件:

login.php login.php

<?php
require_once "config.php";

$redirectURL = 'https://' . $_SERVER[ 'SERVER_NAME' ] . '/r/fb-callback.php';
$permissions = ['email','user_photos','user_posts'];
$loginUrl = $helper->getLoginUrl($redirectURL, $permissions);
?>

<a href='<?php echo $loginUrl; ?>'>
<img src='continue-with-facebook.png'>
</a>
?>

config.php config.php

<?php
if( !session_id() ) {
    session_start();
}

require_once '/home/bitnami/vendor/autoload.php';

$fb = new Facebook\Facebook([
  'app_id' => '---',
  'app_secret' => '---',
  'default_graph_version' => 'v3.1',
  ]);

$helper = $fb->getRedirectLoginHelper();
?>

fb-callback.php fb-callback.php

<?php
require_once("config.php");
?>
<html>
<head>
  <script type='text/javascript' src='jquery.js'></script>
  <script>
    var $j = jQuery.noConflict();

    $j(document).ready(function () {

      $j.ajax({
        type: "GET",
        url: "get-posts.php",
        cache: false,
        success: function (html) {
          setTimeout(function () {
            $j('#updateDiv').html(html);
          }, 1000);
        }
      });
    });
  </script>
    </head>
    <body>
        <div id='updateDiv'><img src='spinning.gif' alt='processing...'></div> 
    </body>
</html>

get-posts.php get-posts.php

<?php
require_once("config.php");

// get the posts for this user id
try {
  $accessToken = $helper->getAccessToken();
} catch(Facebook\Exceptions\FacebookResponseException $e) {
  // When Graph returns an error
  echo __LINE__ . ' Access Token: Graph returned an error: ' . $e->getMessage();
  exit;
} catch(Facebook\Exceptions\FacebookSDKException $e) {
  // When validation fails or other local issues
  echo __LINE__ . ' Access Token: Facebook SDK returned an error: ' . $e->getMessage();
  exit;
}

if (! isset($accessToken)) {
  if ($helper->getError()) {
    header('HTTP/1.0 401 Unauthorized');
    echo "Error: " . $helper->getError() . "\n";
    echo "Error Code: " . $helper->getErrorCode() . "\n";
    echo "Error Reason: " . $helper->getErrorReason() . "\n";
    echo "Error Description: " . $helper->getErrorDescription() . "\n";
  } else {
    header('HTTP/1.0 400 Bad Request');
    echo __LINE__ . ' Access Token: Bad request';
  }
  exit;
}

...

Here is the actual code that works with explanations to what had to change below: 这是实际的代码,用于解释以下内容:

fb-callback.php fb-callback.php

<?php
require_once("config.php");

try {
  $accessToken = $helper->getAccessToken();
} catch(Facebook\Exceptions\FacebookResponseException $e) {
  // When Graph returns an error
  echo __LINE__ . ' Access Token: Graph returned an error: ' . $e->getMessage();
  exit;
} catch(Facebook\Exceptions\FacebookSDKException $e) {
  // When validation fails or other local issues
  echo __LINE__ . ' Access Token: Facebook SDK returned an error: ' . $e->getMessage();
  exit;
}

if (! isset($accessToken)) {
  if ($helper->getError()) {
    header('HTTP/1.0 401 Unauthorized');
    echo "Error: " . $helper->getError() . "\n";
    echo "Error Code: " . $helper->getErrorCode() . "\n";
    echo "Error Reason: " . $helper->getErrorReason() . "\n";
    echo "Error Description: " . $helper->getErrorDescription() . "\n";
  } else {
    header('HTTP/1.0 400 Bad Request');
    echo __LINE__ . ' Access Token: Bad request';
  }
  exit;
}

$get = "?accessToken=" . $accessToken;
?>
<html>
<head>
  <script type='text/javascript' src='jquery.js'></script>
  <script>
    var $j = jQuery.noConflict();

    $j(document).ready(function () {

      $j.ajax({
        type: "GET",
        url: "get-posts.php<?php echo $get; ?>",
        cache: false,
        success: function (html) {
          setTimeout(function () {
            $j('#updateDiv').html(html);
          }, 1000);
        }
      });
    });
  </script>
    </head>
    <body>
        <div id='updateDiv'><img src='spinning.gif' alt='processing...'></div> 
    </body>
</html>

get-posts.php get-posts.php

<?php
require_once("config.php");

$fb->setDefaultAccessToken($_GET['accessToken']);

...

So what changed? 那么,什么改变了? First, I needed to get the access code in fb-callback.php, not get-posts.php. 首先,我需要在fb-callback.php中获取访问代码,而不是get-posts.php。 So I moved the logic to get the access code and check for errors back to fb-callback.php. 因此,我将逻辑移到获取访问代码的位置,然后将错误检查回到fb-callback.php。 Then I added some logic to pass the access token collected to the parameter string of the AJAX url. 然后,我添加了一些逻辑,以将收集的访问令牌传递给AJAX url的参数字符串。 (Look for "$get" in two places, once where I set the value and once where I attach it to the AJAX url.) (在两个位置中查找“ $ get”,一个位置设置值,另一个位置将其附加到AJAX网址。)

In get-posts.php, I removed the code that asks the Facebook API for an access token. 在get-posts.php中,我删除了向Facebook API请求访问令牌的代码。 Instead, I merely set the access token based on what was passed from fb-config.php via GET in the parameter named "accessToken" with the setDefaultAccesstoken() function from the Facebook PHP SDK. 取而代之的是,我只是基于Facebook PHP SDK中的setDefaultAccesstoken()函数,基于通过fb-config.php通过GET从fb-config.php传递的参数设置访问令牌,该参数名为“ accessToken”。

As noted elsewhere, you can keep passing along the value of the access token via GET, REQUEST, or $_SESSION to page after page, so long as you maintain a session and inform Facebook via the setDefaultAccessToken() function at each subsequent page. 如其他地方所述,您可以继续通过GET,REQUEST或$ _SESSION将访问令牌的值逐页传递,只要您保持会话并在每个后续页面上通过setDefaultAccessToken()函数通知Facebook。

The answer is in the comments, but there are actually better ways. 答案在注释中,但实际上有更好的方法。


Firstly, to answer your question directly, the issue is that the "code" passed to the fb-callback.php has not been passed to the script that calls $helper->getAccessToken() 首先,直接回答您的问题,问题是传递给fb-callback.php的“代码”尚未传递给调用$helper->getAccessToken()的脚本。

The docs for that function (at https://developers.facebook.com/docs/php/FacebookRedirectLoginHelper/5.0.0 ) states 该功能的文档(位于https://developers.facebook.com/docs/php/FacebookRedirectLoginHelper/5.0.0 )指出

Attempts to obtain an access token from an authorization code. 尝试从授权码中获取访问令牌。 This method will make a request to the Graph API and return a response. 此方法将向Graph API发出请求并返回响应。 If there was an error in that process a FacebookSDKException will be thrown. 如果该过程中有错误,将抛出FacebookSDKException。 A FacebookSDKException will also be thrown if the CSRF validation fails. 如果CSRF验证失败,还将引发FacebookSDKException。

If no authorization code could be found from the code param in the URL, this method will return null. 如果在URL的代码参数中找不到授权代码,则此方法将返回null。

There are two other points to note: 还有两点需要注意:

  • The "state" (cross site forgery token) is part of the session; “状态”(跨站点伪造令牌)是会话的一部分; you do not need to explicitly pass it in so long as you're on the same domain, however you may need session_start() in both login and get-posts scripts There is a parameter to the getAccessToken function which should be the URL of the ORIGINAL 只要您位于同一个域中,就无需显式传递它,但是在login脚本和get-posts脚本中都可能需要session_start()getAccessToken函数有一个参数,该参数应该是原版的

So very simply 所以非常简单

  1. Add session_start() to the login script and the get-posts.php 将session_start()添加到登录脚本和get-posts.php
  2. Modify the fb-callback.php to be something like 修改fb-callback.php为类似

.

<?php
require_once("config.php");
$code = $_GET['code'];   // warning: add validation code exists, sanitise etc.
?>
<html>
<head>
  <script type='text/javascript' src='jquery.js'></script>
  <script>
    var $j = jQuery.noConflict();

    $j(document).ready(function () {

      $j.ajax({
        type: "GET",
        url: "get-posts.php?code=<?php echo $code; ?>",
        cache: false,
        success: function (html) {
          setTimeout(function () {
            $j('#updateDiv').html(html);
          }, 1000);
        }
      });
    });
  </script>
    </head>
    <body>
        <div id='updateDiv'><img src='spinning.gif' alt='processing...'></div> 
    </body>
</html>

(Note: I hate inline PHP - this is example only) (注意:我讨厌嵌入式PHP-这仅是示例)


However: what you should be doing is passing the Access Token between functions and not the oAuth code. 但是:您应该做的是在函数之间传递访问令牌,而不是在oAuth代码之间传递。 The way you have it above (passing the oAuth code) is a one-off; 上面的方式(通过oAuth代码)是一次性的; however you can call get-posts a second/third/fourth time and it'll work if you have the access token first. 但是,您可以第二次/第三次/第四次调用get-posts如果您首先拥有访问令牌,它将可以使用。

1) Do the token exchange in fb-callback.php at the top (it's fast, no need for spinner), grab the token (which FB library stores in a session variable/cookie, or you can do it yourself) and then show the HTML page with spinner and AJAX call. 1)在顶部的fb-callback.php中进行令牌交换(速度很快,不需要微调器),获取令牌(FB库将其存储在会话变量/ cookie中,或者您可以自己完成),然后显示带微调器和AJAX调用的HTML页面。

2) Do the token exchange in fb-callback.php at the top (it's fast, no need for spinner), grab the token (which FB library stores in a session variable/cookie, or you can do it yourself) and then quickly redirect to another page that shows the spinner and does AJAX call. 2)在顶部的fb-callback.php中进行令牌交换(速度很快,不需要微调器),获取令牌(FB库将其存储在会话变量/ cookie中,或者您可以自己完成),然后快速重定向到另一个显示微调器并进行AJAX调用的页面。

The critical think to note in both of these is you are passing the Access Token; 在这两个方面要注意的关键思想是您正在传递访问令牌。 in get-posts.php check "do I have access token; if not - show login button; if so - call facebook". get-posts.php检查“我是否具有访问令牌;如果没有,请显示登录按钮;如果有,请致电Facebook”。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM