Как обновить токен доступа пользователя Facebook, если я имею дело с большим количеством AJAX?
Пожалуйста, скажите мне, правильно ли я понимаю. (потому что я могу и не быть.)
- пользователь публикует что-то на моем сайте. (Он проверил "также опубликовать в Facebook".)
- клиент отправляет запрос AJAX POST на мой сервер, и мой сервер вставляет запись в мою базу данных.
- сервер понимает, что токен доступа пользователя facebook истек, поэтому он отправляет ответ обратно клиенту, сохраняя сообщение в сеансе.
- клиент делает
window.location.replace(facebook_oauth_dialog_url)
- затем пользователь увидит внезапную "вспышку", Перейдя на Facebook, а затем вернется на веб-сайт. Мой сервер получает новый маркер доступа.
- мой сервер проверяет сессии, чтобы увидеть, что должно быть опубликовано в Facebook. И затем он использует новый токен доступа для публикации этого в Facebook.
это действительно так утомительно? Почему я не могу обновить сервер приложения без участия пользователя в диалоговом окне?
весь мой сайт является основой.js. Что значит, это одна большая страница. Я не могу перепрыгивать пользователя между Facebook и моим сайтом, как это.
7 ответов
идея в том, чтобы использовать Facebook JS-SDK методы:
- пользователь Регистрация Сообщение В Facebook опции
- вы проверяете, подключен ли текущий пользователь к вашему приложению (используя
FB.getLoginStatus()
) - если пользователь подключен, у вас есть два варианта:
- сообщение непосредственно с помощью
FB.api
способ или - отправить
access_token
на ваш сервер для завершения процесса post там
- сообщение непосредственно с помощью
- если пользователь не подключен (или не вошел в Facebook), используйте
FB.login()
метод
вот краткий пример (с Live демо!) для начала:
<!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()
на клиенте, чтобы получить последний маркер доступа. При использовании этого метода нет flash и нет взаимодействия с пользователем, так как он просто захватывает новый токен доступа.
FB.getLoginStatus( function ( response ) {
if ( response.authResponse ) {
var accessToken = response.authResponse.accessToken;
//post to server
};
} );
Я надеюсь, вы знали, что если у вас есть разрешение publish_stream, вам не нужен маркер доступа, вот документация для publish_stream и Ниже приведено решение для четырех сценариев
1.Срок действия токена истекает по истечении времени (по умолчанию-2 часа).
2.Пользователь меняет свой пароль, который делает недействительным маркер доступа.
3.Пользователь де-авторизует ваше приложение.
4.Пользователь выходит из Фейсбук.
чтобы обеспечить лучший опыт для ваших пользователей, ваше приложение должно быть готово ловить ошибки для вышеуказанных сценариев. В коде ниже показано, как обрабатывать эти ошибки и получить новый маркер доступа.
при перенаправлении пользователя в диалоговое окно 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;
}
?>
для получения более детально информации вы можете посетить этот ссылке
Спасибо
обновление
ну, вы делаете что-то не так, вам не нужно продлевать токен доступа, даже если его истек все, что вам нужно, это отправить пользователю facebook id & контент, который вы хотите опубликовать вместе на свой сервер ajax, а затем опубликовать его без токена доступа просто проверьте здесь
опубликовать поток из приложения - для не вошедшего в систему пользователя, используя Graph API, php SDK
Если у вас есть разрешение publish_stream, вам не нужен маркер доступа это-документация для publish_stream https://developers.facebook.com/docs/reference/api/permissions/
позволяет вашему приложению публиковать контент, комментарии и лайки для пользователя stream и к потокам друзей пользователя. С этого разрешения, вы можете публиковать контент в ленте пользователя в любое время, без требующее области offline_access. Однако, обратите внимание, что Facebook рекомендует инициированную пользователем модель общего доступа.
У меня проблема в другом проекте.
способ, которым я его обрабатываю, - создать скрытый iframe. В первый раз, когда вам нужно, чтобы пользователь принял привилегию, используйте главное окно для перенаправления. тогда, когда вы уверены, что пользователь уже принял привилегию, используйте скрытый iframe для взаимодействия с facebook.
пользователь не увидит "flash", потому что это будет сделано в iframe.
Я сделал это с GWT. Вот код, который я использовал : это общается с Facebook через iframe и проверяет токен доступа каждые 500 мс, чтобы узнать, действителен ли токен.
код находится в java (скомпилирован в javascript с использованием 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);
}
}
}
надеюсь, это поможет вам.
вы не можете просто выполнить обмен на стороне сервера, потому что это обходит контроль пользователя над авторизацией.
как уже говорили другие, вы должны использовать JavaScript SDK для облегчения обновления маркера доступа. По умолчанию он использует iframe и возвращается во всплывающее окно для связи с Facebook. Это должно хорошо работать с вашим позвоночником.приложение js.
мне нравится определять функцию javascript, которая принимает успех и отрицает обратные вызовы для выполнения после проверка статуса авторизации 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);
}
});
};
это будет идти вперед и работать FB.login
если сеанс пользователя истек. В вашем успехе обратного вызова, вы также можете пройти response.authResponse.signedRequest
как signed_request в ваших данных AJAX POST. Это позволит большинству FB SDK (например, PHP SDK) распознавать и проверять подписанный запрос и устанавливать идентификатор пользователя и маркер доступа. Вы также можете пройти весь response.authResponse
данные с вашего поста. Это имеет accessToken, userID и expiresIn время.
см.https://developers.facebook.com/docs/reference/javascript/FB.getLoginStatus/ для документов на сайте разработчиков Facebook.
кроме того, если вы включите миграцию устаревания автономного доступа, вы можете обменять токен доступа, чтобы продлить срок действия до 60 дней вместо 2 часов по умолчанию. См.https://developers.facebook.com/docs/offline-access-deprecation/
Как сказал @ThinkingStiff, ключевым моментом является то, что вам нужно вызов FB.getLoginStatus () на клиенте, чтобы получить последний токен доступа
в эти дни все классные дети обрабатывают свои логины и извлекают свои маркеры доступа через JavaScript с помощью SDK. А почему бы и нет? Пользователи любят его!
после того, как JavaScript SDK извлекает маркер доступа, все запросы AJAX на ваш сервер также будут иметь доступ к этому маркеру доступа. То есть, это автоматически передается вместе с каждым Запрос AJAX в виде файла cookie.
Итак, на стороне сервера вы можете получить маркер доступа через cookies (у нашего друга StackOverflow есть некоторые ответы, связанные с поиском этого cookie). Однако, если вы сделаете другую классную вещь и используете PHP SDK, вам даже не придется задумываться об этом, потому что он автоматически захватит cookie для вас, если он есть!