2012-02-19 9 views
7

Per favore dimmi se sto capendo correttamente. (perché potrei non esserlo)Come faccio a rinnovare un utente Facebook_access_token se gestisco un sacco di AJAX?

  1. L'utente pubblica qualcosa sul mio sito. (Ha controllato "anche post su Facebook".)
  2. Il client invia una richiesta POST AJAX al mio server e il mio server inserisce il record nel mio database.
  3. Il server realizza che il token di accesso utente di Facebook è scaduto, quindi invia la risposta al client, mentre memorizza il post in una sessione.
  4. Il cliente fa un window.location.replace(facebook_oauth_dialog_url)
  5. Quindi l'utente vedrà un improvviso "lampo", andando a Facebook, poi tornare al sito. Il mio server preleva il nuovo token di accesso.
  6. Il mio server controlla la sessione per vedere cosa deve essere pubblicato su Facebook. E poi, usa il nuovo token di accesso per postarlo su Facebook.

E 'davvero così noioso? Perché non riesco a rinnovare l'app lato server senza che l'utente passi attraverso la finestra di dialogo?

Il mio intero sito è Backbone.js. Ciò significa che è una grande pagina. Non posso saltare l'utente avanti e indietro tra Facebook e il mio sito web come questo.

+6

Ora questa è una taglia :)! – Asken

+0

per offline_access? https://developers.facebook.com/docs/offline-access-deprecation/ –

+0

Quando si rinnova un token di accesso se l'utente è connesso a Facebook, non vede alcuna finestra di dialogo. Qual è esattamente la tua domanda? –

risposta

8

L'idea è di fare uso dei Facebook JS-SDK metodi: verificare

  1. utente del Condividi con i tuoi opzione
  2. di verificare se l'utente corrente è collegato alla vostra applicazione (utilizzando FB.getLoginStatus())
  3. se l'utente è connesso, hai due opzioni:
    • post direttamente utilizzando il metodo FB.api o
    • Inviare il access_token al server per completare il processo di post ci
  4. se l'utente non è collegato (o non è registrato a facebook), utilizzare il FB.login() metodo di

Ecco un rapido esempio (con un diretta Demo!) per voi per iniziare:

<!DOCTYPE html> 
<html xmlns:fb="http://www.facebook.com/2008/fbml"> 
<body> 
<div id="fb-root"></div> 
<script> 
var fbLoaded = false; 
window.fbAsyncInit = function() { 
    FB.init({ 
     appId  : 'YOUR_APP_ID', // App ID 
     //channelUrl : '//WWW.YOUR_DOMAIN.COM/channel.html', // Channel File 
     status  : true, // check login status 
     cookie  : true, // enable cookies to allow the server to access the session 
     xfbml  : true // parse XFBML 
    }); 
    fbLoaded = true; 
    // Additional initialization code here 

}; 

function postForm() { 
    var msg = document.myForm.msg.value; 
    // do form validation here, e.g: 
    if(!msg.length) { 
     alert("You should enter a message!"); 
     return false; 
    } 

    // do we need to post to Facebook? 
    if(document.myForm.toFB.checked) { 
     // is the library loaded? 
     if(!fbLoaded) { 
      alert("Facebook JS-SDK is not yet loaded. Please try again later or uncheck Post To Facebook option"); 
      return false; 
     } 

     FB.getLoginStatus(function(response) { 
      if (response.status === 'connected') { 
       var uid = response.authResponse.userID; 
       var accessToken = response.authResponse.accessToken; 
       /* 
       * message can be posted to Facebook directly 
       * using the FB.api method or accessToken 
       * can be sent to the server and do the call 
       * from there 
       */ 
       myAjaxCall(msg, accessToken); 
      } else { 
       // status is either not_authorized or unknown 
       FB.login(function(response) { 
        if (response.authResponse) { 
         var accessToken = response.authResponse.accessToken; 
         myAjaxCall(msg, accessToken); 
        } else { 
         alert('User cancelled login or did not fully authorize.'); 
        } 
       }, {scope: 'publish_stream'}); 
      } 
     }); 
    } else { 
     myAjaxCall(msg); 
    } 
    return false; 
} 

function myAjaxCall(m,a) { 
    alert("Here you make the ajax call\nMessage: " + m + "\nAccess Token: " + a); 
} 

    // Load the SDK Asynchronously 
    (function(d){ 
    var js, id = 'facebook-jssdk', ref = d.getElementsByTagName('script')[0]; 
    if (d.getElementById(id)) {return;} 
    js = d.createElement('script'); js.id = id; js.async = true; 
    js.src = "//connect.facebook.net/en_US/all.js"; 
    ref.parentNode.insertBefore(js, ref); 
    }(document)); 
</script> 

<form id="myForm" name="myForm" action="post" onSubmit="return postForm()"> 
<p><label>Your Message:</label><br/><textarea name="msg"></textarea></p> 
<p><label>Post to Facebook?</label><input type="checkbox" value="1" name="toFB" /></p> 
<p><input type="submit" value="Submit"></p> 
</form> 
</body> 
</html> 
+2

Risposta perfetta. Come posso darti extra taglie? – TIMEX

+0

Grazie! beh, non ne sono sicuro ... Immagino che dovresti aspettare un paio di giorni prima che tu possa mettere un'altra taglia sulla domanda. Forse è una buona domanda nel [sito Web Meta] (http://meta.stackoverflow.com/). – ifaour

+0

L'aggiornamento di @ Pooya è totalmente valido! una volta che l'utente ha concesso alla tua app l'autorizzazione 'publish_stream'. Non c'è bisogno di un 'access_token' (l'ID utente è sufficiente. Controlla la mia risposta [qui] (http://facebook.stackoverflow.com/questions/4814432/publishing-to-users-wall-without-being-online-logged -in-facebook-sharing-usin/4816134 # 4816134). Tuttavia, poiché l'utente è online durante la pubblicazione, l'utilizzo di '/ me/feed' + utente' access_token' nel backend è ancora un approccio valido! – ifaour

2

Prima di postare sul server, chiamare il FB.getLoginStatus() sul client per ottenere l'ultimo token di accesso. Non c'è flash quando si utilizza questo metodo e nessuna interazione da parte dell'utente, in quanto semplicemente afferra un nuovo token di accesso.

FB.getLoginStatus(function (response) { 
    if (response.authResponse) { 
     var accessToken = response.authResponse.accessToken; 
     //post to server 
    }; 
}); 
0

Ho il problema in un altro progetto.

Il modo in cui lo gestisco è creare un iframe nascosto. La prima volta che hai bisogno che l'utente accetti il ​​privilegio, usa la tua finestra principale per reindirizzare. quindi, quando sei sicuro che l'utente abbia già accettato il privilegio, usa l'iframe nascosto per comunicare con Facebook.

L'utente non vedrà il "flash" perché verrà eseguito in un iframe.

L'ho fatto con GWT. Ecco il codice che ho usato: comunica con Facebook tramite l'iframe e fa un controllo sul token di accesso ogni 500ms per vedere se il token è valido.

Il codice è in java (compilato in javascript con gwt).

public class FacebookConnector extends Composite 
{ 
     public static final String          ARG_ACCESS_TOKEN_EXPIRES  = "fb_accessTokenExpires"; 
     public static final String          ARG_GAME_FACEBOOK_NAME   = "gameFBName"; 
     public static final String          ARG_GAME_FACEBOOK_ID   = "gameFBId"; 

     private static FacebookConnectorUiBinder  uiBinder          = GWT.create(FacebookConnectorUiBinder.class); 

     interface FacebookConnectorUiBinder extends UiBinder<Widget, FacebookConnector> 
     { 
     } 

     private static FacebookConnector  me; 

     public static FacebookConnector getInstance() 
     { 
       if (me == null) 
       { 
         me = new FacebookConnector(); 
       } 

       return me; 
     } 

     @UiField 
     IFrameElement iframe; 

     private Date accessToken; 
     private Timer timer; 

     protected FacebookConnector() 
     { 
       initWidget(uiBinder.createAndBindUi(this)); 

       if (ArgManager.getArg(ARG_ACCESS_TOKEN_EXPIRES) != null) 
       { 
         accessToken = new Date(Long.parseLong(ArgManager.getArg(ARG_ACCESS_TOKEN_EXPIRES))); 
       } 
     } 

     public void checkAccessToken(final AbstractAsyncCallback<Void> callback) 
     { 
       if (accessToken == null || accessToken.before(new Date())) 
       { 
         // send authentication 
         String url = "https://graph.facebook.com/oauth/authorize?client_id=" 
             + ArgManager.getArg(ARG_GAME_FACEBOOK_ID) + "&scope=user_birthday,email&redirect_uri=" 
             + ArgManager.getArg(ArgManager.ARG_URL_FACEBOOK_BASE) + "page/facebook-step2%3FgameName%3D" 
             + ArgManager.getGameShortcut(); 

         iframe.setSrc(url); 

         // check url 
         timer = new Timer() { 

           @Override 
           public void run() 
           { 
             ClientFactory.getInstance().getService().getAccessTokenExpires(new AbstractAsyncCallback<Date>() { 

               @Override 
               public void onSuccess(Date result) 
               { 
                 super.onSuccess(result); 

                 if (result != null && result.after(new Date())) 
                 { 
                   accessToken = result; 

                   // call the callback 
                   callback.onSuccess(null); 
                 } 
                 else 
                 { 
                   // try again in one second 
                   timer.schedule(1000); 
                 } 

               } 

             }); 

           } 
         }; 

         // launch timer in 500 milliseconds 
         timer.schedule(500); 
       } 
       else 
       { 
         callback.onSuccess(null); 
       } 
     } 
} 

Spero che ti possa aiutare.

2

spero si noto che se si ha il permesso publish_stream non hai bisogno di token di accesso qui è la documentazione per publish_stream e Di seguito è la soluzione per quattro scenari

1. Il gettone scade dopo scadere del tempo (2 ore è l'impostazione predefinita) .
2. L'utente modifica la propria password che invalida il token di accesso.
3. L'utente de-autorizza la tua app.
4. L'utente si disconnette da Facebook.

Per garantire la migliore esperienza per i vostri utenti, la vostra app deve essere preparata a rilevare gli errori per gli scenari di cui sopra. Il seguente codice PHP mostra come gestire questi errori e recuperare un nuovo token di accesso.

Quando si reindirizza l'utente alla finestra di dialogo di autorizzazione, all'utente non vengono richieste autorizzazioni se l'utente ha già autorizzato l'applicazione. Facebook ti restituirà un token di accesso valido senza alcuna finestra di dialogo con l'utente. Tuttavia, se l'utente ha de-autorizzato la tua applicazione, l'utente dovrà ri-autorizzare la tua applicazione per ottenere l'access_token.

<?php 
$app_id = "YOUR_APP_ID"; 
$app_secret = "YOUR_APP_SECRET"; 
$my_url = "YOUR_POST_LOGIN_URL"; 

// known valid access token stored in a database 
$access_token = "YOUR_STORED_ACCESS_TOKEN"; 

$code = $_REQUEST["code"]; 

// If we get a code, it means that we have re-authed the user 
//and can get a valid access_token. 
if (isset($code)) { 
$token_url="https://graph.facebook.com/oauth/access_token?client_id=" 
    . $app_id . "&redirect_uri=" . urlencode($my_url) 
    . "&client_secret=" . $app_secret 
    . "&code=" . $code . "&display=popup"; 
$response = file_get_contents($token_url); 
$params = null; 
parse_str($response, $params); 
$access_token = $params['access_token']; 
} 


// Attempt to query the graph: 
$graph_url = "https://graph.facebook.com/me?" 
. "access_token=" . $access_token; 
$response = curl_get_file_contents($graph_url); 
$decoded_response = json_decode($response); 

//Check for errors 
if ($decoded_response->error) { 
// check to see if this is an oAuth error: 
if ($decoded_response->error->type== "OAuthException") { 
    // Retrieving a valid access token. 
    $dialog_url= "https://www.facebook.com/dialog/oauth?" 
    . "client_id=" . $app_id 
    . "&redirect_uri=" . urlencode($my_url); 
    echo("<script> top.location.href='" . $dialog_url 
    . "'</script>"); 
} 
else { 
    echo "other error has happened"; 
} 
} 
else { 
// success 
echo("success" . $decoded_response->name); 
echo($access_token); 
} 

// note this wrapper function exists in order to circumvent PHP’s 
//strict obeying of HTTP error codes. In this case, Facebook 
//returns error code 400 which PHP obeys and wipes out 
//the response. 
function curl_get_file_contents($URL) { 
$c = curl_init(); 
curl_setopt($c, CURLOPT_RETURNTRANSFER, 1); 
curl_setopt($c, CURLOPT_SSL_VERIFYPEER, false); 
curl_setopt($c, CURLOPT_URL, $URL); 
$contents = curl_exec($c); 
$err = curl_getinfo($c,CURLINFO_HTTP_CODE); 
curl_close($c); 
if ($contents) return $contents; 
else return FALSE; 
} 
?> 

per maggiori dettagli informazioni è possibile visitare questo link
Grazie

0

Non si può semplicemente fare uno scambio lato server perché che aggira il controllo dell'utente dell'autorizzazione.

Come altri hanno già detto, è necessario utilizzare il sdk javascript per facilitare l'aggiornamento del token di accesso. Per impostazione predefinita, utilizza un iframe e torna a un popup per gestire la comunicazione con Facebook. Questo dovrebbe funzionare bene con l'applicazione backbone.js.

mi piace definire una funzione javascript che prende il successo e ha negato callback da eseguire dopo la verifica dello stato di autenticazione facebook:

function checkFBAuth(success, denied, scope) { 
    FB.getLoginStatus(function (response) { 
     if (response.status === 'connected') { 
      success(response); 
     } else { 
      FB.login(function(response) { 
       if (response.status === 'connected') { 
        success(response); 
       } else { 
        denied(response); 
       } 
      }, scope); 
     } 
    }); 
}; 

Questo andrà avanti ed eseguire FB.login se la sessione dell'utente è scaduto. Nella tua callback di successo, potresti anche passare response.authResponse.signedRequest come signed_request nei tuoi dati POST AJAX. Ciò consentirà alla maggior parte degli SDK dell'FB (ad esempio, l'SDK PHP) di riconoscere e convalidare la richiesta firmata e impostare l'ID utente e il token di accesso. Potresti anche passare tutti i dati response.authResponse con il tuo POST. Questo ha l'accessToken, l'userID e la scadenza nel tempo.

Vedere https://developers.facebook.com/docs/reference/javascript/FB.getLoginStatus/ per i documenti sul sito di Facebook Developers.

Inoltre, se si abilita la migrazione di deprecazione dell'accesso offline, è possibile scambiare il token di accesso per estendere la data di scadenza a 60 giorni invece delle 2 ore predefinite. Vedere https://developers.facebook.com/docs/offline-access-deprecation/

2

UPDATE

bene si sta facendo qualcosa di sbagliato che non è necessario rinnovare token di accesso, anche se scaduto tutto ciò che serve è l'invio utente facebook id & contenuto da inviare insieme al server da ajax poi post-it senza token di accesso Basta controllare su qui

Publish Stream from the application - for non logged in user, using Graph API, php SDK

se avete il permesso publish_stream non avete bisogno di token di accesso questo è Documentazio n per publish_stream https://developers.facebook.com/docs/reference/api/permissions/

Attiva la tua app per inviare contenuti, commenti, e ama flusso di un utente e ai flussi di amici dell'utente. Con questa autorizzazione, puoi pubblicare contenuti sul feed di un utente in qualsiasi momento, senza che richiede offline_access. Tuttavia, tieni presente che Facebook consiglia un modello di condivisione avviato dall'utente.

+0

+1! Non so come mi sia sfuggito di mente! – ifaour

0

Come @ThinkingStiff Detto questo, il punto chiave è che è necessario chiamata FB.getLoginStatus() sul client per ottenere l'ultimo token di accesso

In questi giorni, tutti i bambini freschi sono movimentazione loro login e recupero dei loro token di accesso tramite JavaScript con l'SDK. E hey, perché no? Gli utenti lo adorano!

Dopo che l'SDK JavaScript recupera il token di accesso, tutte le richieste AJAX sul server avranno anche accesso a quel token di accesso. Cioè, viene automaticamente passato insieme a ciascuna richiesta AJAX sotto forma di cookie.

Quindi, sul lato server, è possibile recuperare il token di accesso tramite cookie (il nostro amico StackOverflow ha alcune risposte relative alla ricerca di tale cookie). Tuttavia, se fai l'altra cosa interessante e usi l'SDK di PHP, non dovrai nemmeno pensarci, perché prenderà automaticamente il cookie per te, se è lì!

+0

L'SDK di Javascript è la strada da percorrere per questo, è un'esperienza utente di gran lunga migliore. Il percorso di back-end è noioso. –

Problemi correlati