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も有効にしていない場合は、正常に機能が低下します。
OK、OmniAuthをDeviseと組み合わせて使用している場合、Chris Healdのソリューションに問題があります。問題は、ウィンドウ(つまりログインページ)をリロードすると、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を渡す必要があります。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にリダイレクトされ、正しいフラッシュメッセージが表示されます。
いくつかのテストを行った後、このソリューションでは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を使用してpopup
という単純なパラメーターをURLに追加することです。 OmniAuthは、リクエストURLに追加されたクエリパラメータを格納するのに十分親切です。最後に、コントローラーでそのパラメーターを確認します。存在する場合は、JavaScriptが有効になっていることが原因です。
if request.env['omniauth.params']['popup']
render 'callback', :layout => false
else
redirect_to @after_sign_in_url
end
また、failure
アクションについても同じことを行うことを忘れないでください。これは、ユーザーがログインを受け入れないときに呼び出されます。
クリスヒールドの解決策なしでは、これを行うことはできなかったでしょう。
他の人を助けるために投稿する。私は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" %>
これは、ここのセルジオグティエレスのヒントから直接です- https://coderwall.com/p/bsfitw