使用Firebase简单登录保护路由 [英] Protecting a route using Firebase Simple Login

查看:97
本文介绍了使用Firebase简单登录保护路由的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正尝试在使用Firebase Simple登录和 ember-cli 的Ember应用程序中实现以下顺序的事件。


  1. 检查用户是否在允许进入任何路由之前进行身份验证。

  2. 如果用户未通过身份验证,则重定向到 LoginRoute 。如果用户被认证,请允许他们进入路由。

为了完成第1步,我重新打开 Ember.Route ,并实现一个 beforeModel 钩子。

 $ $ $ $ $ $ $ 



初始化:(容器,应用程序) - >
#注册LoginController与所有控制器/路由
application.register'main:auth',LoginController
application.inject'route','auth','main:auth'
application.inject'controller','auth','main:auth'
application.inject'main:auth','store','store:main'

#确保用户是允许进入之前登录
Ember.Route.reopen
beforeModel:(transition) - >
@transitionTo'login'if!@get('auth.isAuthed')

`导出默认AuthInitializer`

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



LoginController 简单地实例化一个新的 FirebaseSimpleLogin 对象,并注册相应的回调函数。 >

  LoginController = Ember.ObjectController.extend 
#为简洁起见,某些控制器被省略...

auth:null
isAuthed:false

init: - >
dbRef = new Firebase('https://dawnbreaker.firebaseio.com')
@set('auth',new FirebaseSimpleLogin(dbRef,@ authCompleted.bind(@)))
@_super()

authCompleted:(错误,用户) - >
如果错误
#处理无效的登录尝试..
否如果用户
#处理成功登录..
除非@get('isAuthed')
@set('currentUserId',user.id)
@set('isAuthed',true)
@transitionToRoute('index')
else
#处理注销..
@set('currentUserId',null)
@set('isAuthed',false)

`导出默认LoginController`
/ pre>

我的实现有两个问题。




  • LoginController 首先初始化, isAuthed 设置为false。因此,当 authCompleted 完成时,该应用将永远重定向到索引

  • beforeModel 钩子执行之前 c $ c $ authCompleted callback finish ,导致钩子重定向到登录



页面的结果刷新是


  1. 登录模板闪烁一秒。

  2. 应用程序转换为 index

每个页面刷新以丢失其当前位置(重定向到索引路由)。



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

解决方案

完全是我的意见,但我喜欢将资源树中的auth部分。它不需要是url的一部分,但可以是。使用这种方法,它仍然可以使用全局控制器(根据从呼叫返回的内容将被挂起,或者如果您在登录中获取的话,则会连接一些其他连接)。

  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;
//可以跳过回调当地财产
返回$ .getJSON('/ auth')然后(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){
//也许重定向,如果自动等...
});
},
authCompleted:function(error,user){
var defer = this.get('defer');
// if authenticated
defer.resolve({auth:true});
// else authenticated
defer.resolve({auth:false});
}


I'm trying to implement the following sequence of events in an Ember app that uses Firebase Simple Login and ember-cli.

  1. Check if the user is authenticated before allowing entry to any route. All routes need to be authenticated.
  2. If the user is not authenticated, redirect to LoginRoute. If the user is authenticated, allow them to enter the route.

In order to accomplish step 1, I reopen Ember.Route in an initializer and implement a beforeModel hook.

`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`

The above code does indeed redirect to login if the user is not currently logged in.

LoginController simply instantiates a new FirebaseSimpleLogin object and registers the appropriate callback function.

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`

There is two problems with my implementation.

  • When LoginController first initializes, isAuthed is set to false. Therefore, when authCompleted finishes, the app will always redirect to index.
  • The beforeModel hook executes before the authCompleted callback finishes, causing the hook to redirect to login.

What results from a page refresh is

  1. The login template flashes for a second.
  2. The app transitions to index.

This causes every page refresh to lose its current location (redirecting to the index route).

The question is, how can I protect a route using Ember and Firebase Simple Login? Any help would be appreciated.

解决方案

Totally my opinion, but I like making the auth part of the resource tree. It doesn't need to be part of the url, but can be. Using this way, it can still use a global controller (it will be hooked up based on what's returned from the call, or some other hookup if you fetch it in the login).

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

In the case of a non-promise callback, you can create your own promise, and resolve that when appropriate.

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});      
}

这篇关于使用Firebase简单登录保护路由的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆