Facebook授权Rails应用程序:为什么我们需要做服务器和客户端授权?

时间:2013-02-19 08:04:18

标签: ruby-on-rails facebook omniauth

在Ryan的Railscast Facebook授权中,他最后添加了一些Facebook SDK javascript,以“通过服务器端授权降低facebook客户端授权”。但是,我没有看到它的使用。如果我们已经使用omniauth从服务器端设置了授权,为什么我们必须再次添加客户端授权?它有什么不同?

引用的javascript代码是(来自链接的Railscast):

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: '<%= ENV["FACEBOOK_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

更新

我们需要将FB.login授权与服务器端授权集成的原因之一可能是,如果在Facebook iFrame中访问Omniauth服务器端授权,则无法使用该授权。如果用户第一次访问应用程序,则应用程序必须请求权限;但是,无法在iFrame中加载oAuth权限对话框以防止点击劫持。调用FB.login可以避免此类问题,因为它会将权限框显示为弹出窗口(Omniauth弹出选项不起作用)。

所以现在我有一个真正的理由来集成客户端授权,但Railscasts的代码不适用于我当前的设置。我选择以下列方式做到这一点。

现在,我的application.html.erb中有以下脚本:

<script>
    // Additional JS functions here
    window.fbAsyncInit = function() {
      FB.init({
        appId      : <%= ENV['FACEBOOK_KEY'] %>, // App ID
        status     : true, // check login status
        cookie     : true, // enable cookies to allow the server to access the session
        xfbml      : true  // parse XFBML
      });
    };

    // Load the SDK Asynchronously
    (function(d){
       var js, id = 'facebook-jssdk', ref = d.getElementsByTagName('script')[0];
       if (d.getElementById(id)) {return;}
       js = d.createElement('script'); js.id = id; js.async = true;
       js.src = "//connect.facebook.net/en_US/all.js";
       ref.parentNode.insertBefore(js, ref);
     }(document));

  </script>

在我看来,我有以下链接调用Facebook登录行动:

<%= link_to 'log in with facebook', '/auth/facebook', id: 'fb_log_in_link' %>

我将以下脚本添加到我有登录链接的视图页面。

function login() {
  FB.login(function(response) {
    if (response.authResponse) {
      window.location = '/auth/facebook/callback'
    }
  });
}

另外,我需要更改链接以调用函数,而不是指向/auth/facebook/

<%= link_to_function 'log in with facebook', 'login()' %>

完成!服务器端和客户端授权完全集成。由于在看完Ryan的Railscast之后我仍然感到困惑,我想为那些可能也感到困惑的人添加一些解释。

这种方式有效:

  1. Facebook页面加载时会启动Facebook SDK。
  2. 用户点击“使用Facebook登录”链接。
  3. FB.login函数由链接调用,用户将完成所有权限过程(例如,显示要求用户权限的权限对话框)。
  4. 然后,用户被定向到/auth/facebook/callback。从routes.rb我们就有match 'auth/:provider/callback', to: 'sessions#create'行。因此,现在服务器将创建一个新用户,或者只是在用户之前已经注册过的情况下创建一个会话。
  5. 完成!用户已登录。
  6. 合并服务器端和客户端授权有两个主要优点: 1.如果用户在Facebook内部(通过appcenter)登录应用程序,他也将登录Facebook外的应用程序。反之亦然,如果用户登录Facebook外,如果他在Facebook之后访问它,他将自动登录。 2.如果用户在Facebook iFrame中登录,则使用/auth/facebook登录不起作用。为防止点击劫持 Facebook禁止提示用户在Facebook iFrame中进行身份验证权限对话框。避免这种情况的唯一方法是在单独的弹出窗口中打开对话框,使用FB.login登录可以解决问题。

2 个答案:

答案 0 :(得分:1)

它只是说,

Facebook提供了一个JavaScript SDK,我们可以使用它来验证客户端的用户,这样它就不会像他们离开我们的应用程序那样查看它们。

这意味着这是为了让客户端了解当用户从应用程序返回时,它看起来并不像他们确实离开了它。

答案 1 :(得分:1)

简短的回答是 - 你没有。
您可以选择客户端登录(通过javascript SDK)和服务器端登录使用omniauth
服务器端登录的不足使服务器过载,以便您可以从客户端进行呼叫 优点是通常令牌更长(3个月令牌,而不是客户端1-2小时) 我建议combine the two。使用客户端进行初始登录,一旦你这样做,就可以从服务器端获得扩展令牌的异步调用(仅当你必须这样做时)。