【问题标题】:Best way to enforce user/authentication state in Ember.JS app在 Ember.JS 应用程序中强制执行用户/身份验证状态的最佳方法
【发布时间】:2014-02-15 02:09:39
【问题描述】:

正在开发我的第一个 EmberJS 应用程序。整个应用程序要求用户登录。我试图围绕强制用户现在(最初加载页面时)和将来(当用户注销时)登录的最佳方式并且没有刷新)。

我已经处理了用户身份验证钩子 - 现在我有一个 ember-data 模型和关联的存储连接,用于处理授权用户和创建用户“会话”(使用 sessionStorage)。

我不知道该怎么做是强制用户在跨路由转换时进行身份验证,包括根路由中的初始转换。我把这个逻辑放在哪里?如果我有一个身份验证状态管理器,我如何将它连接到路由中?我应该有根路由之外的身份验证路由吗?

注意:如果这个问题措辞不当或者我需要更好地解释什么,请告诉我,我很乐意这样做。

编辑: 我最终做了一些我认为更像 ember-esque 的事情,尽管可能是一个混乱的实现。我有一个身份验证状态管理器,它存储当前用户的身份验证密钥以及当前状态。

每当需要验证时,它都会简单地向 authmanager 请求它并传递一个回调函数以使用验证密钥运行。如果用户没有登录,它会拉出一个登录表单,在用户登录之前暂停回调函数。

这是我正在使用的部分代码。需要清理,我遗漏了一些东西。 http://gist.github.com/3741751

【问题讨论】:

  • this fiddle中有一个认证状态的示例实现。
  • 是的,我记得看到过这个,但我从来没有仔细研究过源代码,因为除了单击登录按钮时闪烁“登录/注销”之外,该示例似乎并没有做太多事情。 .try 未经授权不会做任何事情。从源代码来看,登录似乎应该列出新闻,但从来没有。我会更多地研究源代码,看看我是否可以使用这个例子。
  • 也许您可以创建一个基本控制器来为您进行检查,并让您当前的控制器extend 它已经内置了该功能。同样,您可以拥有一个基本视图(绑定到某种“已验证”属性),您将 extend 到您当前的视图,因此您可以将模板更改为“您必须验证”类型的东西,如果用户未通过身份验证。至于 REST,一旦用户在服务器中通过身份验证,您可能希望实现一个 API 令牌来提供客户端应用程序,并且对于每个请求,发送并验证该令牌是真实的
  • @MilkyWayJoe 我想过。但是当我在路由中调用 connectOutlets 时,模型调用是在控制器启动之前进行的。就我而言,我在每个模型调用中发送一个 API 令牌,没有令牌 = 错误请求。我想我可以把它放在模型中,但是检查登录用户似乎有点晚了
  • 我有同样的问题需要解决。除了上述解决方案之外,我还在考虑实施一种基本上独立于 Ember 应用程序本身的身份验证[不完全——这就是为什么它仍然是一个计划]。我之前使用过这样的 HTML5 服务器发送事件:boxed.hu/articles/html5-server-sent-events,并计划用于处理用户身份验证状态。到目前为止我还没有给它太多时间,但我会围绕它做一些测试。

标签: authentication ember.js


【解决方案1】:

如果您需要在初始状态转换之前执行检查,Ember.Application 类上有一个特殊功能,称为deferReadiness()。来自源代码的注释:

默认情况下,路由器将开始尝试将当前 URL 转换为 浏览器发出DOMContentReady 事件后的应用程序状态。如果你 需要延迟路由,可以调用应用程序的deferReadiness()方法。 一旦可以开始路由,调用advanceReadiness() 方法。

请注意,在撰写本文时,此功能仅在 ember-latest 中可用

【讨论】:

  • 嗯。很高兴知道。是每次状态转换时调用此函数,还是仅在最初加载页面时调用此函数?我目前正在使用 ember-data 的边缘构建,但它与 ember-latest 不太兼容。所以我以后一定要试试这个。
  • 仅在页面初始加载时。 IMO,检查每个状态转换的身份验证工作量太大。在我们的应用程序中,我们执行以下操作 - 在初始化时,我们检查用户是否经过身份验证,然后我们建立到服务器的持久连接。此连接的存在告诉我们用户已通过身份验证。如果由于某种原因连接终止,则连接管理器会将我们的应用程序转换为访客模式。
  • @tokarev 你是如何实现持久连接的?
  • @EduárdMoldován、websockets、长轮询等
【解决方案2】:

在路由转换之间重新检查身份验证方面,您可以在Ember.Routeenterexit方法中添加钩子:

var redirectToLogin = function(router){
    // Do your login check here.
    if (!App.loggedIn) {
        Ember.run.next(this, function(){
            if (router.currentState.name != "login") {
                router.transitionTo('root.login');
            }
        })
    }
};

// Define the routes.
App.Router = Ember.Router.extend({
    root: Ember.Route.extend({
        enter: redirectToLogin,
        login: Ember.Route.Extend({
            route: 'login',
            exit: redirectToLogin,
            connectOutlets: function(router){
                router.get('applicationController').connectOutlet('login');
            }
        }),
        ....
    })
});

这种解决方案的问题是 Ember 实际上会在转换回您的登录路由之前转换到新路由(并因此加载所有数据等)。因此,这可能会暴露您不希望他们再看到的应用程序的某些部分。然而,现实情况是所有这些数据仍然加载在内存中,并且可以通过 JavaScript 控制台访问,所以我认为这是一个不错的解决方案。

还请记住,由于 Ember.Route.extend 返回一个新对象,您可以创建自己的包装器,然后在整个应用程序中重用它:

App.AuthenticatedRoute = Ember.Route.extend({
    enter: redirectToLogin
});
App.Router = Ember.Router.extend({
    root: Ember.Route.extend({
        index: App.AuthenticatedRoute.extend({
            ...
        })
    })
});

如果您使用上述解决方案,那么您可以准确挑选您验证的路由。您还可以在redirectToLogin 中删除“检查他们是否正在转换到登录屏幕”检查。

【讨论】:

    【解决方案3】:

    我整理了一个超级简单的包来管理会话和身份验证,名为 Ember.Session https://github.com/andrewreedy/ember-session

    【讨论】:

    • 虽然此链接可能会回答问题,但最好在此处包含答案的基本部分并提供链接以供参考。如果链接页面发生更改,仅链接的答案可能会失效。
    • 有趣的是,与旧版本的 ember-simple-auth ember-session 看起来有多么相似。几乎可以得到它在很大程度上只是复制和重新标记的印象......
    【解决方案4】:

    还请看一下: http://www.embercasts.com/

    那里有两个关于身份验证的截屏视频。

    谢谢。

    【讨论】:

      猜你喜欢
      • 2015-12-21
      • 2013-08-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-11
      相关资源
      最近更新 更多