Facebook Connect и HTTP Cookies - Как я могу преодолеть это "состояние гонки" - PullRequest
3 голосов
/ 19 июля 2010

Если вам интересно, что такое «условие гонки», это недостаток системы, в то время как он сильно зависит от времени. См. Вики здесь для получения дополнительной информации.

Итак, у меня есть условие, касающееся Facebook Connect и реализации службы единого входа с веб-приложением ASP.NET 4.0 (Аутентификация на основе форм - IIS7).

Сам процесс (включая выход из системы) работает хорошо, но .....

Вот сценарий, где он не работает точно на 100%:

  1. Пользователь входит в Facebook.
  2. Пользователь переходит на мой сайт.
  3. Пользователь не вошел в систему автоматически (хотя должно быть).
  4. Пользователь обновляет страницу и автоматически входит в систему.

Когда я остановил код на шаге 3 - куки-файлы Facebook еще не появились (в HttpContext.Current.Request.Cookies).

Но когда страница перезагружается (шаг 4) - там есть куки-файлы Facebook.

Для меня это может быть несколько вещей:

Я не уверен, что только в случае Facebook нет , пока не предоставил доступ к моему приложению для доступа к файлам cookie (задержка междоменного рукопожатия - xd_receiver.htm) или проблема с междоменные файлы cookie и жизненный цикл страницы ASP.NET.

Кто-нибудь еще имел дело с этой проблемой?

Это не "все и все в конце концов", но это раздражает (и не очень хорошо с точки зрения пользователя).

EDIT:

Хорошо, теперь я заметил что-то странное. Если я захожу в Facebook (через Facebook) и жду, скажем, 20 секунд, а затем захожу на мой сайт, он ВСЕ ЕЩЕ не регистрирует меня. Только после второй загрузки он входит в систему. Так что, возможно, это не проблема синхронизации - почему Нужно ли 2 обновления, чтобы прочитать куки?

Чтобы устранить некоторую путаницу - Facebook устанавливает файлы cookie (чтобы пользователь вошел в Facebook), а мой веб-сайт считывает эти файлы cookie.

Это происходит при каждом запросе страницы (логика в пользовательском элементе управления, который находится на каждой странице)

protected void Page_PreRender(object sender, EventArgs eventArgs)
{
   if (FacebookUser.IsAuthenticated) // static property, checks HttpContext.Request.Cookies
   {
        // log them into my website
   }
}

Итак, при первом обновлении - в HttpContext.Request.Cookies ничего нет.

При втором обновлении они есть.

Я думаю, что причина этого в том, что FB.Init выполняется на стороне клиента при каждом запросе страницы. Это то, что инициализирует куки. Поэтому, когда вы впервые заходите на мой сайт (после входа в Facebook), на стороне сервера (где я проверяю куки), эта функция еще не была запущена.

Так что я думаю, что здесь я проигрываю битву (пытаюсь получить доступ к куки-серверу, который установлен на стороне клиента).

РЕДАКТИРОВАТЬ 2:

Вот мой код инициализации (запускается на window.load):

FB.init('myapikey', 'xd_receiver.htm', null);

Я сейчас пытаюсь сделать что-то вроде этого:

FB.init('myapikey', 'xd_receiver.htm', null);
FB.getLoginStatus(function(response) {
  if (!response.session) {
      return false;
  }
  else {
    window.location.reload();
  }
});

Но я получаю ошибку JavaScript - "FB.getLoginStatus" не является функцией. = (

Это потому, что я использую следующую библиотеку JavaScript: http://static.ak.connect.facebook.com/js/api_lib/v0.4/FeatureLoader.js.php/en_US

Принимая во внимание, что другие люди говорят использовать это: http://connect.facebook.net/en_US/all.js

Я искал в документации новый API JS.

Для ссылки на других, кто наткнулся на этот поток, вот документация для «старого» JS API: http://developers.facebook.com/docs/reference/oldjavascript/

Итак, я решил эту проблему с помощью FB.Connect.get_status () и перезагрузки окна, если пользователь прошел аутентификацию.

Спасибо всем за помощь.

Это моё «решение» проблемы, если кому-то ещё есть дело:

window.onload = function() { 
                FB.init('{0}', 'xd_receiver.htm');
                FB.ensureInit(function() {
                   FB.Connect.ifUserConnected(onUserConnected, onUserNotConnected); 
                });
            };

            function onUserConnected() {
                alert('connected!');
                window.location.reload();
            }

            function onUserNotConnected() {
                alert('not connected');
            }

Конечно, вы должны проверить cookie проверки подлинности с помощью форм перед выполнением window.location.reload (), иначе страница будет просто обновляться. =) * +1087 *

Ответы [ 4 ]

1 голос
/ 20 июля 2010

Это не «состояние гонки», и его можно лучше охарактеризовать как побочный эффект от работы аутентификации на основе браузера. Здесь задействованы три «актера»:

  1. Ваша заявка
  2. Facebook
  3. Пользователь

Когда пользователь посещает ваше приложение, Facebook еще не участвует в этом процессе. Это означает, что вы не знаете, является ли Пользователь пользователем Facebook, который уже авторизовался с вашим Приложением, потому что у Facebook еще не было возможности сообщить вам об этом. Вот почему вы не получаете куки в первом запросе.

Теперь, когда ваше приложение отвечает на этот запрос, оно включает в себя JavaScript Facebook. JavaScript SDK будет пинговать Facebook в фоновом режиме с помощью IFrame (, если вы скажете использовать опцию status: true или более явно ), и получите ответ от него, основанный на Пользователе, в настоящее время вошедшем в Facebook (если есть). На этом этапе, если сеанс был возвращен (то есть, есть вошедший в систему пользователь, который авторизовал ваше приложение в прошлом), Facebook JavaScript SDK установит файл cookie (, если вы сообщите это можно сделать с помощью опции cookie: true ).

Так вот логика, почему первый запрос не получает куки. Помимо настройки файлов cookie, вы также можете получать уведомления об этом через JavaScript Events , которые позволят вам выполнить определенные действия. Наиболее распространенное действие - просто перезагрузить страницу и позволить серверу заметить недавно установленные файлы cookie и отобразить соответствующий подписанный вид. Но другой вариант - использовать Ajax и сделать что-то более необычное, не требующее перезагрузки всей страницы.

Что касается того, почему это происходит только для вас при секунде загрузки страницы, я не уверен. Но вот как это работает:)

ПРИМЕЧАНИЕ. Я не входил в сценарий использования advanced , который включает в себя полное перенаправление страницы в качестве недокументированной, но поддерживаемой конечной точки (той же, что используется в JavaScript SDK), которая предоставляет иллюзия исправления этой проблемы. Я настоятельно рекомендую использовать JavaScript SDK, поскольку он предоставляет гораздо более простое и в целом более производительное решение при небольших затратах на удобство использования. Но если тебе это небезразлично, я мог бы остановиться и на этом.

0 голосов
/ 18 августа 2010

У меня была такая же проблема.Причина, по которой перезагрузки страниц работают, заключается в том, что они вызывают повторный вызов FB.init () (что, я подозреваю, является функцией, которая фактически устанавливает cookie).перезагрузка страницы.Вот стилизованная версия того, что я написал.Я не знаю, правильный ли это путь, но он, безусловно, работает ... FB.getLoginStatus(function(response) { if (response.session) { window.location.href = '/connect/cb/fb'; } else{ FB.login( function(resp){FBResponse(resp);},perms); }<br> });</p> <p>var FBResponse = function(response,stop){ if (response.session){ window.location.href = '/connect/cb/fb'; } else{ if (stop) return; FB.init({appId:FBappId, status:true, cookie:true, xfbml:true}); FB.getLoginStatus(function(resp){FBResponse(resp,'stop');}); }; }

0 голосов
/ 18 августа 2010

У меня точно такая же проблема. Не могли бы вы выяснить причину этого? Удивительно, но это работает для меня на моем производственном сервере, но не на локальном (я изменил свой / etc / host для ссылки на localhost как peta.edu из-за проблем, связанных с localhost)

Многократное обновление у меня тоже не работает. Но если я вручную нажму на строку URL и нажму Enter, она будет работать нормально.

С уважением,

Nithin.

0 голосов
/ 19 июля 2010

Поскольку вы не можете контролировать точку входа в состояние гонки (вход пользователя в Facebook), существует ограниченное количество вариантов:

  1. Добавьте задержку на шаге 3 (возможно, несколько миллисекунд сна дадут Facebook достаточно времени, чтобы подписать ваше использование). Это будет иметь неприятный эффект частичного исправления: оно будет работать в «большинстве» случаев и вызовет задержку для всех ваших входов в систему.

  2. Если аутентификация завершается неудачей на шаге 3, ТОГДА подождите несколько миллисекунд (проверьте, чтобы найти правильную сумму), а затем попытайтесь снова выполнить аутентификацию. Только после этого отобразите страницу без аутентификации.

  3. Если это проблема жизненного цикла страницы (маловероятно), добавьте дополнительную страницу / редирект для своей страницы входа. То есть ваш процесс будет выглядеть так:

    а) пользователь заходит на фейсбук
    б) пользователь переходит на ваш сайт (файл cookie еще не установлен)
    в) пользователь перенаправлен на страницу входа (может быть установлен cookie). Если пользователь еще не аутентифицирован, подождите 100 мс, а затем перенаправьте на шаг б) (только один раз).
    г) пользователь вошел в систему

...