omniauth facebook 로그인을 팝업으로 전환
저는 레일과 함께 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, Devise 와 함께 OmniAuth를 사용하는 경우 Chris Heald의 솔루션에 문제가 있습니다. 문제는 로그인 페이지에있는 창을 다시로드 할 때 Devise가 액세스하려는 URL을 완전히 무시하고 root_path로 이동하고 "You are already signed in"오류 메시지를 표시한다는 것입니다. 이는 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의 메서드를 사용하여 해당 URL을 가져올 수 있습니다 after_sign_in_path_for
.
마지막으로 뷰를 렌더링해야합니다. 뷰를 사용하여 일부 자바 스크립트를 호출하기 때문에 레이아웃을 렌더링 할 필요가 없으므로 속도를 늦추지 않도록 해제합니다. 그보기는 다음과 같습니다.
# 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
JavaScript를 사용하여 URL에 호출되는 간단한 매개 변수를 추가하는 것 입니다. OmniAuth는 요청 URL에 추가 된 쿼리 매개 변수를 저장하기에 충분히 친절합니다. 마지막으로 컨트롤러에서 해당 매개 변수를 확인합니다. 존재하는 경우 JavaScript가 활성화되어 있기 때문입니다.
if request.env['omniauth.params']['popup']
render 'callback', :layout => false
else
redirect_to @after_sign_in_url
end
또한 failure
사용자가 로그인을 수락하지 않을 때 호출되는 작업에 대해 동일한 작업 을 수행하는 것을 잊지 마십시오 .
크리스 힐드의 솔루션 없이는 할 수 없었습니다. 그래서 .. 정말 감사합니다!
Posting in case it helps others. I was using Chris Heald's answer but ran into trouble with the final bit of javascript closing any new window links. For example, if I posted a link to my site onto Facebook, when users clicked the link the new window would automatically close in Chrome because the condition only checks for "if(window.opener)"
I ended up solving this with the use of a global variable (popupValue). There may be more elegant solutions but thought I'd share in case others hit the same issue:
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()
}
});
I wound up using Facebook's JS SDK since it's easier.
# 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
Then in your views:
<%= link_to "Sign in with Facebook", "/auth/facebook", id: "sign_in" %>
<%= link_to "Sign out", signout_path, id: "sign_out" %>
This is directly from Sergio Gutierrez's tip here - https://coderwall.com/p/bsfitw
참고URL : https://stackoverflow.com/questions/4491433/turn-omniauth-facebook-login-into-a-popup
'program story' 카테고리의 다른 글
http 라이브 스트리밍 m3u8 파일의 FFMPEG mp4? (0) | 2020.12.10 |
---|---|
Android에서 데이터베이스 파일을 SD 카드에 어떻게 백업합니까? (0) | 2020.12.10 |
jQuery는 한 클래스를 다른 클래스로 바꿉니다. (0) | 2020.12.10 |
활동에서 조각이 생성되었을 때 null을 반환하는 getView (0) | 2020.12.10 |
Postman으로 NTLM 통과 (0) | 2020.12.10 |