backbone.js - 处理用户是否已登录

42

首先,应该将静态页面设置为应用程序的登录页面吗?

其次,我的服务器端代码很好(不会提供用户不应看到的数据)。但是,我如何让我的应用程序知道如果用户未登录,则返回登录表单?

5个回答

70

我使用会话概念来控制用户的登录状态。

我有这样一个 SessionModel 和 SessionCollection:

SessionModel = Backbone.Model.extend({
    defaults: {
        sessionId: "",
        userName: "",
        password: "",
        userId: ""
    },

    isAuthorized: function(){
       return Boolean(this.get("sessionId"));
    }

});
在应用启动时,我会初始化一个全局变量activeSession。在开始时,此会话未经授权,任何绑定到此模型实例的视图都可以相应地呈现。在尝试登录时,我首先通过使该会话失效来注销。
logout = function(){
    window.activeSession.id = "";
    window.activeSession.clear();
}

这将触发任何监听activeSession的视图,并将我的主视图设置为登录模式,其中它会出现一个登录提示。然后我从用户那里获取用户名和密码,并像这样在activeSession上设置它们:

login = function(userName, password){
    window.activeSession.set(
        {
            userName: userName,
            password: password
        },{
            silent:true
        }
    );
    window.activeSession.save();
}
这会通过backbone.sync触发对服务器的更新。在服务器上,我已经设置了session资源的POST操作,以便它检查userName和password。如果有效,则在session上填充用户详细信息、设置唯一的session id并移除密码,然后发送结果。

我的backbone.sync还被设置为将window.activeSession的sessionId添加到任何向服务器发出的请求中。如果服务器上的sessionId无效,则会发送HTTP 401,从而触发logout(),进而显示登录提示框。

我们还没有完全实现这个功能,所以逻辑可能存在错误,但基本上是这样实现的。另外,上面的代码不是我们实际的代码,因为它包含一些处理逻辑,但这就是大概的意思。

我实际上改变了一下行为。现在我通过sessionCollection.create()创建新的会话,然后触发一个全局可用的loginSuccess消息,任何视图都可以监听它。 - Jens Alm
2
仍然值得分享一些教程或甚至是一个小示例。当然,感谢您的解释。 - montrealist
有人知道如何在注销时触发DELETE请求吗?window.activeSession.destroy()对我来说没有发送任何请求。 - jackocnr
1
我找到了解决方案:你需要先给它一个ID,否则BB会认为它还没有在数据库中持久化,因此不会发送DELETE请求:window.activeSession.set("id", 0); - jackocnr
我一直在使用一个全局的 user 模型,它会从未登录状态变成游客再到注册用户。它类似于上面描述的会话模型,但还包括用户配置文件信息。这在很多情况下运行得非常好,因为 Backbone 中的事件监听很适合这种用例。登录/注册屏幕侦听 error,任何 UI 元素都可以侦听 sync。它可以有像 .logOut 这样的方法。到目前为止,唯一的问题是操作的时间和顺序,但我仍然认为这种方法是可靠的。 - SimplGy
显示剩余2条评论

14

我的静态页面(index.php)通过客户端代码调用后端请求以检查当前用户是否已登录。假设您有一个后端调用api/auth/logged_in,如果用户已登录则返回HTTP状态码200,否则返回400(使用基于cookie的会话):

appController.checkUser(function(isLoggedIn){
    if(!isLoggedIn) {
        window.location.hash = "login";    
    }

    Backbone.history.start();
});

...

window.AppController = Backbone.Controller.extend({

  checkUser: function(callback) {
     var that = this;

     $.ajax("api/auth/logged_in", {
       type: "GET",
       dataType: "json",
       success: function() {
         return callback(true);
       },
       error: function() {
         return callback(false);
       }
     });
  }
});

您如何在接收任何数据之前进行检查?以便每次应用程序调用数据时,它都会检查是否已登录。如果没有登录,则跳转到登录页面。 - Matthew
9
如果您想在每次调用后端时都进行检查,那么应该将其与后端代码集成。例如,如果用户未经身份验证即进行任何调用,则可以从后端返回“401未经授权”或客户端可以捕获的其他内容。这样一来,您就不必在每个数据请求之前进行单独的授权检查了。在这种情况下,您可能需要覆盖“Backbone.sync”方法以捕获“401未经授权”,并发出某些事件,您可以使用该事件来检测是否未经授权地调用了后端。 - Sam

5

2
我认为您不仅应该控制HTML的显示,还应该控制显示的数据。因为用户可以使用Firefox更改您的JavaScript代码。
具体来说,您应该在用户登录后给予用户一个令牌,每次他或她访问您的组件(例如数据网格或树形结构等)时,页面必须从您的Web服务中提取这些数据(可能是JSON格式),并且Web服务将检查此令牌。如果令牌不正确或已过期,则不应向用户提供数据,而应提供错误消息。这样,即使用户使用Firebug更改js代码,也无法破解您的安全性。
希望这能对您有所帮助。

-14

我认为你应该只在服务器端进行这个操作... 因为有很多被黑客攻击的可能性,除非你有某种惊人的API来响应它。


8
你应该在服务器端也这样做,但只要不依赖于它,检测客户端的登录状态也没有问题。 - Duncan Bayne

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接