Включите omniauth facebook войти в всплывающее окно
Я использую omniauth gem с rails, и он отлично работает с регистрацией пользователей, но каждый раз, когда он доставляет вас на страницу входа fb, затем перенаправляет вас обратно. Мне было интересно, есть ли способ сделать то, что делает большинство страниц, и показать вход fb во всплывающем окне, а затем перезагрузить Родительский div после завершения. Есть идеи?
спасибо!
4 ответа:
конечно, вы можете легко.
на ваш взгляд:
=link_to "Log in with Facebook", omniauth_authorize_path(:user, :facebook), :class => "popup", :"data-width" => 600, :"data-height" => 400
в вашем приложении.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 auth в центрированном всплывающем окне 600x400, а затем, когда пользователь вернется из аутентификации, представление закроет всплывающее окно и обновит родительскую страницу. Он изящно деградирует, если пользователь ctrl-щелкает ссылку или не имеет включенного Javascript.
хорошо, так что есть проблема с решением Криса Хилда, если вы используете OmniAuth в сочетании с разработки. Проблема в том, что при перезагрузке окна (то есть на странице входа в систему) Devise приведет вас к root_path, полностью игнорируя url-адрес, к которому вы пытались получить доступ, и выдаст сообщение об ошибке "вы уже вошли в систему". Это имеет смысл, потому что 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
так обычно, после поиска или создания пользователя с помощью хэша, возвращенного определенным поставщиком (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 <script type="text/javascript"> window.opener.location = '<%= @after_sign_in_url %>'; window.close(); </script>
таким образом, пользователь перенаправляется на правильный 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-адрес запроса. Поэтому, наконец, мы проверяем этот параметр в контроллере. Если он существует, это потому, что JavaScript включено:if request.env['omniauth.params']['popup'] render 'callback', :layout => false else redirect_to @after_sign_in_url end
кроме того, не забудьте сделать то же самое для вашего
failure
действие, которое вызывается, когда пользователь не принимает входа.Я не мог бы сделать это без решения Криса Хилда, так что.. Большое вам спасибо!
размещение в случае, если это помогает другим. Я использовал ответ Криса Хилда, но столкнулся с проблемой с последним битом javascript, закрывающим любые новые ссылки на окна. Например, если я разместил ссылку на свой сайт на Facebook, когда пользователи нажали ссылку, новое окно автоматически закроется в Chrome, потому что условие проверяет только "если(окно.открывалка)"
Я решил это с помощью глобальной переменной (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 Facebook, так как это проще.
# In facebook.js.coffee jQuery -> $('body').prepend('<div id="fb-root"></div>') $.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