Включите учетную запись omniauth facebook во всплывающем окне

Я использую жемчужину omniauth с рельсами, и он отлично работает с входом в систему, но каждый раз, когда вы переходите на страницу входа в fb, вы перенаправляете назад. Мне было интересно, есть ли способ сделать то, что делает большинство страниц, и показать вход в fb во всплывающем окне, а затем перезагрузить родительский div после завершения. Есть идеи?

Благодаря!

Конечно, вы можете легко.

На ваш взгляд:

 =link_to "Log in with Facebook", omniauth_authorize_path(:user, :facebook), :class => "popup", :"data-width" => 600, :"data-height" => 400 

В вашем приложении application.js:

 function popupCenter(url, width, height, name) { var left = (screen.width/2)-(width/2); var top = (screen.height/2)-(height/2); return window.open(url, name, "menubar=no,toolbar=no,status=no,width="+width+",height="+height+",toolbar=no,left="+left+",top="+top); } $("a.popup").click(function(e) { popupCenter($(this).attr("href"), $(this).attr("data-width"), $(this).attr("data-height"), "authPopup"); e.stopPropagation(); return false; }); 

И затем в вашем обратном просмотре:

 :javascript if(window.opener) { window.opener.location.reload(true); window.close() } 

Это выведет ваш Facebook-аутентификатор в центре экрана 600×400, а затем, когда пользователь вернется с проверки подлинности, представление закроет всплывающее окно и обновит родительскую страницу. Он изящно деgradleирует, если пользователь ctrl-клики по ссылке или не поддерживает Javascript.

Хорошо, поэтому есть проблема с решением Криса Хелда, если вы используете OmniAuth совместно с Devise . Проблема заключается в том, что при перезагрузке windows (на странице входа) Devise приведет вас к корневому пути, полностью игнорируя URL-адрес, к которому вы пытались получить доступ, и выдает сообщение об ошибке «Вы уже вошли». Это имеет смысл, потому что Devise защищает зарегистрированного пользователя от доступа к странице входа, перенаправляя на домашнюю страницу. Перегружая страницу входа сразу после входа в систему, вы столкнетесь с этой проблемой.

Поэтому мое решение для кого-то, использующего Devise, выглядит следующим образом:

 # add this wherever needed in your_authentications_or_callbacks_controller.rb sign_in user @after_sign_in_url = after_sign_in_path_for(user) render 'callback', :layout => false 

Поэтому, как правило, после обнаружения или создания пользователя, использующего hash, возвращаемый определенным провайдером (Facebook, Twitter и т. Д.), Мы будем называть функцию Devise sign_in_and_redirect . Но мы еще не можем перенаправить (помните, что сейчас пользователь находится во всплывающем окне), поэтому мы просто sign_in имя пользователя.

Затем, нам нужно передать URL-адрес, который пользователь пытался получить к представлению, и мы можем получить этот url, используя метод Devise after_sign_in_path_for .

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

 # views/your_authentications_or_callbacks/callback.html.erb  

Таким образом, пользователь будет перенаправлен на правильный URL-адрес после входа в систему и отобразится соответствующее флэш-сообщение.

С отключенным JavaScript

После некоторого тестирования я понял, что это решение не разрешает аутентификацию без JavaScript, поэтому я хотел бы добавить дополнение.

 function popupCenter(linkUrl, width, height, name) { var separator = (linkUrl.indexOf('?') !== -1) ? '&' : '?', url = linkUrl + separator + 'popup=true', left = (screen.width - width) / 2, top = (screen.height - height) / 2, windowFeatures = 'menubar=no,toolbar=no,status=no,width=' + width + ',height=' + height + ',left=' + left + ',top=' + top; return window.open(url, name, windowFeatures); } 

Изменение здесь добавляет простой параметр, называемый popup к URL-адресу с использованием JavaScript. OmniAuth будет достаточно любезен, чтобы сохранить любые параметры запроса, добавленные в url запроса. Итак, наконец, мы проверяем этот параметр в controllerе. Если он существует, это связано с тем, что JavaScript включен:

 if request.env['omniauth.params']['popup'] render 'callback', :layout => false else redirect_to @after_sign_in_url end 

Кроме того, не забудьте сделать то же самое для вашего действия failure , которое вызывается, когда пользователь не принимает вход в систему.

Я не мог бы сделать это без решения Криса Хедла, так что .. Большое вам спасибо!

Проводка в случае, если она помогает другим. Я использовал ответ Криса Хейлда, но столкнулся с проблемой, когда последний бит javascript закрывал любые новые ссылки на windows. Например, если я разместил ссылку на мой сайт на Facebook, когда пользователи нажмут на ссылку, новое окно автоматически закроется в Chrome, потому что условие проверяет только «if (window.opener)»,

Я решил это решить с помощью глобальной переменной (popupValue). Могут быть более элегантные решения, но я думал, что буду делиться ими, если другие попадут в одну и ту же проблему:

 function popupCenter(url, width, height, name) { var left = (screen.width/2)-(width/2); var top = (screen.height/2)-(height/2); popupValue = "on"; return window.open(url, name, "menubar=no,toolbar=no,status=no,width="+width+",height="+height+",toolbar=no,left="+left+",top="+top ); } $(document).ready(function(){ $("a.popup").click(function(e) { popupCenter($(this).attr("href"), $(this).attr("data-width"), $(this).attr("data-height"), "authPopup"); e.stopPropagation(); return false; }); if(window.opener && window.opener.popupValue === 'on') { delete window.opener.popupValue; window.opener.location.reload(true); window.close() } }); 

Я закончил использовать JS SDK от Apple, так как это проще.

 # In facebook.js.coffee jQuery -> $('body').prepend('
') $.ajax url: "#{window.location.protocol}//connect.facebook.net/en_US/all.js" dataType: 'script' cache: true window.fbAsyncInit = -> FB.init(appId: 'YOUR-APP-ID', cookie: true) $('#sign_in').click (e) -> e.preventDefault() FB.login (response) -> window.location = '/auth/facebook/callback' if response.authResponse $('#sign_out').click (e) -> FB.getLoginStatus (response) -> FB.logout() if response.authResponse true

Тогда в ваших взглядах:

 <%= link_to "Sign in with Facebook", "/auth/facebook", id: "sign_in" %> <%= link_to "Sign out", signout_path, id: "sign_out" %> 

Это прямо из подсказки Серджио Гутьерреза – https://coderwall.com/p/bsfitw

  • Перенос Rails для таблицы join_and_belongs_to_many join
  • Одностраничное приложение и токен CSRF
  • Rails: перенаправить все неизвестные маршруты в root_url
  • Rails: кнопки Multi-submit в одной форме
  • Динамические страницы ошибок в Rails 3
  • Серийный цикл ActiveRecord с использованием JSON вместо YAML
  • Как использовать длинный идентификатор в Rails-приложениях?
  • Вложенные rails content_tag
  • Как отменить конкретную миграцию?
  • Как интегрировать тему Wrap Bootstrap в приложение Rails?
  • Как проверить ответ JSON с помощью RSpec?
  • Давайте будем гением компьютера.