使用Firebase简单登录保护路线

时间:2014-06-15 22:49:55

标签: ember.js firebase emberfire

我正在尝试在使用Firebase简单登录和ember-cli的Ember应用中实施以下事件序列。

  1. 在允许用户进入任何路由之前,请检查用户是否已通过身份验证。 所有路由都需要进行身份验证。
  2. 如果用户未经过身份验证,请重定向到LoginRoute。如果用户已通过身份验证,请允许他们输入路由。
  3. 为了完成第1步,我在初始化程序中重新打开Ember.Route并实现beforeModel挂钩。

    `import LoginController from "tracking/controllers/login"`
    
    AuthInitializer =
      name: 'authInitializer'
    
      initialize: (container, application) ->
        # Register LoginController with all controllers/routes
        application.register 'main:auth', LoginController
        application.inject 'route', 'auth', 'main:auth'
        application.inject 'controller', 'auth', 'main:auth'
        application.inject 'main:auth', 'store', 'store:main'
    
        # Ensure user is logged in before allowing entry
        Ember.Route.reopen
          beforeModel: (transition) ->
            @transitionTo 'login' if !@get('auth.isAuthed')
    
    `export default AuthInitializer`
    

    如果用户当前未登录,则上述代码确实会重定向到login

    LoginController只是实例化一个新的FirebaseSimpleLogin对象并注册相应的回调函数。

    LoginController = Ember.ObjectController.extend
      # Some of the controller is omitted for brevity...
    
      auth: null
      isAuthed: false
    
      init: ->
        dbRef = new Firebase('https://dawnbreaker.firebaseio.com')
        @set('auth', new FirebaseSimpleLogin(dbRef, @authCompleted.bind(@)))
        @_super()
    
      authCompleted: (error, user) ->
        if error
          # Handle invalid login attempt..
        else if user
          # Handle successful login..
          unless @get('isAuthed')
            @set('currentUserId', user.id)
            @set('isAuthed', true)
            @transitionToRoute('index')
        else
          # Handle logout..
          @set('currentUserId', null)
          @set('isAuthed', false)
    
    `export default LoginController`
    

    我的实施存在两个问题。

    • 首次LoginController初始化时,isAuthed设置为false。因此,当authCompleted完成后,应用将始终重定向到index
    • beforeModel挂钩在 authCompleted回调完成之前执行,导致挂钩重定向到login

    页面刷新的结果是

    1. login模板闪烁一秒钟。
    2. 该应用已转换为index
    3. 这会导致每次页面刷新失去当前位置(重定向到index路径)。

      问题是,如何使用Ember和Firebase简单登录保护路线?任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:3)

完全是我的意见,但我喜欢制作资源树的auth部分。它不需要成为网址的一部分,但也可以。使用这种方式,它仍然可以使用全局控制器(它将根据从调用返回的内容进行连接,或者如果您在登录中获取它,则进行其他连接)。

App.Router.map(function() {
  this.resource('auth', {path:''}, function(){
    this.resource('foo');
    this.resource('bar', function(){
      this.route('baz')
    });
  });
  this.route('login');
});

App.AuthRoute = Em.Route.extend({
  model: function(params, transition){
    var self = this;
    // you can skip calling back with a local property
    return $.getJSON('/auth').then(function(result){
      if(!result.good){
        self.transitionTo('login');
      }
      return result;
    });
  }
}); 

http://emberjs.jsbin.com/OxIDiVU/668/edit

如果是非承诺回调,您可以创建自己的承诺,并在适当的时候解决。

model: function(){
  var defer = Ember.RSVP.defer(),
      firebase = new Firebase('https://dawnbreaker.firebaseio.com'),
      fbLogin = new FirebaseSimpleLogin(firebase, this.authCompleted.bind(this));


  this.setProperties({
      defer: defer, 
      firebase: firebase,
      fbLogin: fbLogin
  });

  return defer.promise.then(function(result){
    // maybe redirect if authed etc...
  });
},
authCompleted: function(error, user){
  var defer = this.get('defer');
  //if authenticated
  defer.resolve({auth:true});      
  //else authenticated
  defer.resolve({auth:false});      
}