[英]How do I renew a Facebook user_access_token if I deal with a lot of AJAX?
如果我理解正確,請告訴我。 (因為我可能不會。)
window.location.replace(facebook_oauth_dialog_url)
這真的很乏味嗎? 如果沒有用戶通過對話框,為什么我不能更新應用服務器端?
我的整個網站是Backbone.js。 這意味着,這是一個重要的頁面。 我不能像這樣在Facebook和我的網站之間來回跳轉用戶。
我們的想法是利用Facebook JS-SDK方法:
FB.getLoginStatus()
) FB.api
方法發布或 access_token
發送到您的服務器以完成那里的后期處理 FB.login()
方法 這是一個快速示例(使用現場演示 !)供您開始使用:
<!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>
在發布到服務器之前,請在客戶端上調用FB.getLoginStatus()
以獲取最新的訪問令牌。 使用此方法時沒有閃存,也沒有用戶交互,因為它只是抓取一個新的訪問令牌。
FB.getLoginStatus( function ( response ) {
if ( response.authResponse ) {
var accessToken = response.authResponse.accessToken;
//post to server
};
} );
我希望你知道如果你有publish_stream權限你不需要訪問令牌這里是publish_stream的文檔, 下面是四個場景的解決方案
1.令牌在到期后到期(默認為2小時)。
2.用戶更改他/她的密碼,使訪問令牌無效。
3.用戶取消對您的應用的授權。
4.用戶退出Facebook。
為確保為用戶提供最佳體驗,您的應用需要准備好捕獲上述方案的錯誤。 以下PHP代碼向您展示了如何處理這些錯誤並檢索新的訪問令牌。
將用戶重定向到auth對話框時,如果用戶已經授權您的應用程序,則不會提示用戶輸入權限。 Facebook將返回一個有效的訪問令牌,而無需任何面向用戶的對話框。 但是,如果用戶取消了您的應用程序的授權,則用戶需要重新授權您的應用程序才能獲得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;
}
?>
有關詳細信息,請訪問此鏈接
謝謝
UPDATE
好吧你做錯了什么你不需要更新訪問令牌,即使它已經過期所有你需要的是發送用戶的臉書ID和內容,你想通過ajax一起發布到你的服務器然后發布它沒有訪問令牌只是在這里檢查
如果您有publish_stream權限,則不需要訪問令牌,這是publish_stream的文檔https://developers.facebook.com/docs/reference/api/permissions/
使您的應用能夠將內容,評論和喜歡發布到用戶的信息流和用戶朋友的信息流。 有了此權限,您可以隨時將內容發布到用戶的Feed,而無需offline_access。 但請注意,Facebook建議使用用戶啟動的共享模型。
我在另一個項目中遇到了問題。
我處理它的方法是創建一個隱藏的iframe。 您第一次需要用戶接受該權限時,請使用主窗口進行重定向。 然后,當您確定用戶已經接受了該權限時,請使用隱藏的iframe與Facebook通信。
用戶不會看到“flash”,因為它將在iframe中完成。
我用GWT完成了它。 這是我使用的代碼:它通過iframe與Facebook通信,每隔500ms檢查一次訪問令牌,看看令牌是否有效。
代碼在java中(使用gwt在javascript中編譯)。
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);
}
}
}
希望它會對你有所幫助。
您不能簡單地進行服務器端交換,因為它繞過了用戶對授權的控制。
像其他人所說,你應該使用javascript sdk來方便更新訪問令牌。 默認情況下,它使用iframe並返回彈出窗口以處理與Facebook的通信。 這應該適用於你的backbone.js應用程序。
我喜歡定義一個javascript函數,該函數在檢查facebook auth狀態后取消成功並拒絕執行回調:
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);
}
});
};
如果用戶的會話已過期,這將繼續運行FB.login
。 在成功回調中,您還可以在您的AJAX POST數據中將response.authResponse.signedRequest
作為signed_request傳遞。 這將允許大多數FB SDK(例如,PHP SDK)識別並驗證簽名請求並設置用戶ID和訪問令牌。 您還可以使用POST傳遞整個response.authResponse
數據。 它具有accessToken,userID和expiresIn time。
有關Facebook Developers網站上的文檔,請參閱https://developers.facebook.com/docs/reference/javascript/FB.getLoginStatus/ 。
此外,如果啟用脫機訪問棄用遷移,則可以交換訪問令牌以將到期日期延長至60天而不是默認的2小時。 請參閱https://developers.facebook.com/docs/offline-access-deprecation/
就像@ThinkingStiff所說,關鍵是你需要在客戶端調用FB.getLoginStatus()來獲取最新的訪問令牌
如今,所有酷孩子都在使用SDK處理他們的登錄並通過JavaScript檢索他們的訪問權限。 嘿,為什么不呢? 用戶喜歡它!
在JavaScript SDK檢索訪問令牌之后,對服務器的所有AJAX請求也將有權訪問該訪問令牌。 也就是說,它會以cookie的形式自動傳遞每個AJAX請求。
因此,在服務器端,您可以通過cookie檢索訪問令牌(我們的朋友StackOverflow有一些與查找該cookie相關的答案)。 但是,如果你做了另一件很酷的事情並使用PHP SDK,你甚至不需要再考慮一下,因為它會自動為你抓取cookie,如果有的話!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.