使用Firebase简单登录保护路由 [英] Protecting a route using Firebase Simple Login
问题描述
我正尝试在使用Firebase Simple登录和 ember-cli
的Ember应用程序中实现以下顺序的事件。
- 检查用户是否在允许进入任何路由之前进行身份验证。
- 如果用户未通过身份验证,则重定向到
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
/ pre>
#为简洁起见,某些控制器被省略...
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`
我的实现有两个问题。
- 当
LoginController
首先初始化,isAuthed
设置为false。因此,当authCompleted
完成时,该应用将永远重定向到索引
。 -
beforeModel
钩子执行之前 c $ c $ authCompleted callback finish ,导致钩子重定向到登录
。
页面的结果刷新是
-
登录
模板闪烁一秒。 - 应用程序转换为
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
.
- Check if the user is authenticated before allowing entry to any route. All routes need to be authenticated.
- 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, whenauthCompleted
finishes, the app will always redirect toindex
. - The
beforeModel
hook executes before theauthCompleted
callback finishes, causing the hook to redirect tologin
.
What results from a page refresh is
- The
login
template flashes for a second. - 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屋!