簡體   English   中英

將omniauth facebook登錄變為彈出窗口

[英]Turn omniauth facebook login into a popup

我正在使用帶有rails的omniauth gem,它可以很好地登錄用戶,但每次它都會帶你到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()
  }

這將在一個居中的600x400彈出窗口中彈出您的Facebook身份驗證,然后當用戶從身份驗證返回時,視圖將關閉彈出窗口並刷新父頁面。 如果用戶按住Ctrl鍵單擊鏈接,或者沒有啟用Javascript,它會優雅地降級。

好吧,如果你將OmniAuth與Devise結合使用,Chris Heald的解決方案就會出現問題。 問題是,當您重新加載窗口(即登錄頁面上)時,Devise會將您帶到root_path,完全忽略您嘗試訪問的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

通常,在使用某個提供商(Facebook,Twitter等)返回的哈希查找或創建用戶之后,我們將調用Devise函數sign_in_and_redirect 但是我們還不能重定向(記住,現在,用戶當前處於彈出窗口中),所以我們只需sign_in用戶。

接下來,我們需要傳遞用戶嘗試訪問視圖的url,然后我們可以使用Devise的方法after_sign_in_path_for獲取該url。

最后,我們需要渲染視圖。 由於我們只使用視圖調用一些JavaScript,因此無需渲染布局,因此我們將其關閉以免使我們放慢速度。 這是該觀點:

# views/your_authentications_or_callbacks/callback.html.erb
<script type="text/javascript">
  window.opener.location = '<%= @after_sign_in_url %>';
  window.close();
</script>

這樣,用戶在登錄后會被重定向到正確的URL,並顯示正確的flash消息。

禁用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);
}

這里的更改是使用JavaScript向url添加一個名為popup的簡單參數。 OmniAuth將足以存儲添加到請求URL的任何查詢參數。 所以最后我們在控制器中檢查那個參數。 如果它存在,那是因為啟用了JavaScript:

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

此外,不要忘記為您的failure操作執行相同操作,該操作在用戶不接受登錄時調用。

沒有Chris Heald的解決方案,我不可能做到這一點,所以..非常感謝你!

發布,以防它幫助他人。 我正在使用Chris Heald的答案,但是最后一點關閉任何新窗口鏈接的javascript遇到了麻煩。 例如,如果我在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()
}
});

我使用Facebook的JS SDK,因為它更容易。

# 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" %>

這是直接來自Sergio Gutierrez的提示 - https://coderwall.com/p/bsfitw

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM