Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/60.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails 将omniauth facebook登录变成弹出窗口_Ruby On Rails_Facebook_Omniauth - Fatal编程技术网

Ruby on rails 将omniauth facebook登录变成弹出窗口

Ruby on rails 将omniauth facebook登录变成弹出窗口,ruby-on-rails,facebook,omniauth,Ruby On Rails,Facebook,Omniauth,我将omniauth gem与rails一起使用,它对登录用户非常有效,但每次它将您带到fb登录页面,然后将您重定向回。我想知道是否有一种方法可以像大多数页面那样,在弹出窗口中显示fb登录,然后在完成后重新加载父div。有什么想法吗 谢谢 当然,你可以很容易地做到 在你看来: =link_to "Log in with Facebook", omniauth_authorize_path(:user, :facebook), :class => "popup", :"data-width"

我将omniauth gem与rails一起使用,它对登录用户非常有效,但每次它将您带到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与设计结合使用,Chris Heald的解决方案会出现问题。问题是,当您重新加载窗口(即登录页面上)时,Desive会将您带到根路径,完全忽略您试图访问的url,并会产生错误消息“您已登录”。这是有意义的,因为Desive通过重定向到主页来保护登录用户不访问登录页面。通过在登录后立即重新加载登录页面,您将遇到此问题

因此,对于使用设计的人,我的解决方案如下:

# 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等)返回的哈希值查找或创建用户后,我们会调用design函数
sign\u in\u和\u redirect
。但是我们现在还不能重定向(记住,现在用户正在弹出窗口中),所以我们只需
登录用户

接下来,我们需要传递用户试图访问视图的url,我们可以在为
在路径中签名后使用Desive的方法获取该url

最后,我们需要渲染视图。由于我们将只使用视图来调用一些JavaScript,因此不需要呈现布局,因此我们将其关闭,以免减慢速度。这是一种观点:

# views/your_authentications_or_callbacks/callback.html.erb
<script type="text/javascript">
  window.opener.location = '<%= @after_sign_in_url %>';
  window.close();
</script>
这里的变化是使用JavaScript向url添加一个名为
popup
的简单参数。OmniAuth将非常友好地存储添加到请求url的任何查询参数。最后,我们检查控制器中的参数。如果存在,那是因为启用了JavaScript:

if request.env['omniauth.params']['popup']
  render 'callback', :layout => false
else
  redirect_to @after_sign_in_url
end
另外,不要忘记对您的
失败
操作执行相同的操作,当用户不接受登录时会调用该操作


如果没有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的JSSDK,因为它更简单

# 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
facebook.js.coffee中的
#
jQuery->
$('body')。前缀(“”)
$.ajax
url:“#{window.location.protocol}//connect.facebook.net/en#u US/all.js”
数据类型:“脚本”
缓存:真
window.fbAsyninit=->
FB.init(appId:'YOUR-APP-ID',cookie:true)
$(“#登录”)。单击(e)->
e、 预防默认值()
FB.login(响应)->
window.location='/auth/facebook/callback'if response.authResponse
$(“#注销”)。单击(e)->
FB.getLoginStatus(响应)->
FB.logout()如果response.authResponse
真的
那么在你看来,

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


这直接来自Sergio Gutierrez的提示-

我使用的是Railscast Omniauth方法,回调函数根据不同的逻辑条件使用4种不同的重定向。所以我把你的回调javascript放在application.js中,假设我不再使用弹出窗口,它就会工作。我唯一不喜欢这种方法的地方是,在你输入FB密码登录后,下次你登录时,弹出窗口仍然会短暂出现。我想能够只有当它需要用户输入弹出显示。有什么办法可以做到这一点吗?不幸的是,我不知道有什么办法可以解决这个问题。通常的做法是在主页中进行身份验证循环,因此对用户来说,这看起来就像是重新加载页面,但使用弹出式解决方案,显然无法做到这一点。关于身份验证失败,我只是有一个特殊的弹出模板,我用它来呈现中的错误消息,所以它看起来仍然很好。另一个问题是
window.opener.location。无论什么
在IE7,8中都不起作用。您需要将该代码放在父窗口中,并将其作为函数调用,如
window.opener.my_goto_函数(myurl)
它还应显示为弹出窗口,而不是页面。为此,请按照“我同意Ashitaka”中的说明进行操作。我丢失了flash消息,因为弹出窗口被重定向到一个显示flash消息的页面(因此用户暂时看不到),然后它关闭弹出窗口并重新加载主页。闪光信息消失了,因此用户不知道事情进展顺利。我们如何才能关闭弹出窗口并重新加载页面,而不是点击必要的重定向?这种混淆源于对omniauth的
:display=>“popup”
选项的用途的误解-该选项向Facebook指定,我们希望页面的“显示样式”为弹出窗口调整大小/格式化。该选项并不意味着“将其作为浏览器窗口弹出”-弹出由您执行,如Chris Heald所示。尝试使用Chris的答案并查看登录页面,使用和不使用
:display=>“popup”
选项,在每次更改t之间重新启动服务器
<%= link_to "Sign in with Facebook", "/auth/facebook", id: "sign_in" %>
<%= link_to "Sign out", signout_path, id: "sign_out" %>