3

私は StackOverflow を精査し、ヘルプなしで Facebook にバグを送信しました。私はこれを突き止めるのに 40 時間以上を費やしました。サーバーがURLを有効なクエリ文字列に変更するために重い.htaccess Mod Rewritesを持っている場合、FB.INITとPHPアクセストークンの間の競合であると私は信じています。私はそれをバグとして書きましたが、Facebook はそれがユーザーの問題であると考えています。私は彼らの回答でコードを使用しましたが、まだバグがあります。

元の問題はこちら。私のテスト サイトでは、PHP SDK と JS SDK を組み合わせて問題なく動作させることができます。どちらもログインを許可し、互いに通信して調和して動作します。ページをサーフィンしたり、クライアントを更新しようとしているすべての機能を実行したりするときに問題はありません。

今、私はクライアント サイトに更新された新しい OAuth を、大量の .htaccess mod 書き換えでインストールしようとしています。私のテストサイトには Mod ReWrites がありませんでした。

最初は、PHP で問題なくログインできました。しかし、サイト内の別のページに移動すると、一般的なエラーでアクセス トークンが失われます。現在のユーザーに関する情報を照会するには、アクティブなアクセス トークンを使用する必要があります。

これは、PHP API が失敗したかどうかを確認し、Facebook の独自の認証ページ ( https://graph.facebook.com/oauth/access_tokenに対して ?) から取得した file_get_contents コマンドを使用し、アクセス トークンをリセットすることで修正されました。これはうまくいきました。しかし、これにより FB.init が応答エラーで失敗しました: 現在のユーザーに関する情報を照会するには、アクティブなアクセス トークンを使用する必要があります。FB.api('/me') によるコールバック

したがって、これを回避するには、PHP のアクセス トークンを SESSION に渡し、それを API 呼び出しに配置する必要がありました。FB.api('/me/?access_token=')のように。これはうまくいきました。だから今、私のサイトは支配的なPHPを介してFacebookと連携し、JSは2番目です。

現在の問題: ユーザーがサイトにアクセスし、標準の 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のいずれかを選択し、それらを支配的にして、他方のアクセストークンを強制する必要があります。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 の書き換えでは動作しない場合、それが問題です。

あなたができることは、別のFacebookテストアプリケーションを作成し、modの書き換えなしで別のサーバーにホストし、問題が発生するまで一度に1つずつmodの書き換えを徐々に追加して、どれが原因であるかを確認することです.

于 2011-09-07T20:16:27.383 に答える