9

我在任何地方都找不到太多。大多数示例应用程序只是不谈论安全性等。假设将使用基于休息的 API 调用对用户进行身份验证。应如何构建应用程序以处理身份验证 [还有授权]。指向示例应用程序的指针会很棒。请按单页应用和普通应用添加视图。[我相信每个视图都应该照顾它]

4

3 回答 3

8

您绝对正确,大多数示例根本没有解决安全问题。因此,我没有一个很好的样本可以指给你看。我只能告诉你我们是如何构建我们自己的东西的:

  1. 就像您建议的那样,我们进行 API 调用来验证用户身份。在我们的例子中,只要用户点击第一页(甚至在登录之前),Java 服务器就会创建一个会话 ID,并存储在 cookie 客户端中。由于该 cookie 会随着对服务器的每个 HTTPS 请求(甚至是 AJAX 调用以获取数据或执行命令)一起传播,因此一旦用户通过身份验证,它就会与特定的帐户服务器端相关联。

  2. 假设您到服务器的传输是 HTTPS 并且 cookie 永远不会通过开放的 Internet 传输,那么没有人可以窃听该值并假装是登录用户。

  3. 在我们的例子中,服务器是基于 Java 的,servlet 过滤器位于所有不可公开访问的 API 函数(即需要登录的函数)之前。它在将请求传递给服务之前检查会话并确保它代表登录用户,并保持服务代码不受身份验证检查的影响。然而,授权代码和参数验证目前确实位于服务层中。

  4. 对 API 的 AJAX 调用可能无法通过身份验证,即使由于各种原因(会话已过期、服务器必须重新启动并且忘记了用户的会话、管理员强制注销了用户、 ETC。)。在我们看来,重要的是服务器仍然返回一些东西(即,不是空响应),并且它不应该是重定向到登录页面(这对 AJAX 请求无用)。所以我们总是返回JSend 协议来自我们所有函数的响应,如果用户没有登录,则 servlet 过滤器返回带有特定代码的标准 JSend“错误”响应。这使我们能够让我们的客户端代码(您可以将其放入自定义同步)通知用户未登录并提示登录。您甚至可以在他们登录后自动重试该功能,但这比我们得到的更复杂。

  5. 通过让同步通知用户未登录或违反安全规定,您不必在视图中添加任何特殊内容。他们只是提出他们认为合适的任何要求,要么成功,要么不成功。如果需要重新登录,则会在较低级别触发。

  6. 只要服务器将给定会话标记为不再登录或丢弃会话记录,注销实际上并不需要您终止本地 cookie。

我有点不同意 Derick 的说法,即客户不应该了解安全性。我认为它需要知道何时提示登录,如何告诉服务器何时执行注销,并且我一直认为在客户端进行额外检查以避免意外原则是个好主意。例如,如果我不能使用它们,我宁愿客户端禁止向我显示管理功能,而不是允许我尝试调用它们然后得到错误响应。

最终,服务器绝对必须对每个请求再次检查用户的权限(因为回避客户端安全性非常容易),但良好的 UX 要求客户端知道我不是管理员,因此它可以呈现最佳的代表我的用户界面。

于 2012-06-06T20:27:02.537 回答
5

几个月前在做一个使用基于 REST 的 api 的单页应用程序时遇到了同样的问题。搜索答案后我想出的是使用 HTTP 现有的 401 和 403 错误。我让我的 api 返回这些错误。然后通过使用扩展的错误处理模型来处理这些错误并通过路由器导航功能将它们路由到我的登录来捕获异常。

var ErrorHandlerModel = Backbone.Model.extend({

    initialize: function(attributes, options) {
        options || (options = {});
        this.on("error", this.errorHandler);
        this.init && this.init(attributes, options);
    },

    errorHandler: function(model, error) {
        if (error.status == 401 || error.status == 403) {
          app.history.navigate('login', true);
        }
    }

});

事后看来,虽然我认为只使用全局 jquery ajaxError函数会更好。上面的片段是基于几个月前在此处发布的一个类似问题。

我还必须覆盖主干的默认获取行为,以便我可以触发 ogin 的错误以捕获 api 的 json 响应中包含的响应变量。

var Login = Backbone.Model.extend({  

    urlRoot: '/login',

    parse: function(resp,xhr) {
        if (resp.response == 'success') {
            app.history.navigate('dashboard', true);
        }
        else {
            this.trigger('loginError');     
        }
    return false;
    }
});
于 2012-06-06T21:03:28.853 回答
1

我同意穆的评论。在身份验证方面几乎没有什么可谈的。

您如何处理回传到服务器的标准 HTML 应用程序的身份验证?这样做是因为应该这样做。

对于授权,还有一点要谈,但不多。本质上,您只向用户发送他们被允许看到的内容。除非绝对需要,否则您不会在浏览器中执行授权或身份验证代码。根据我的经验,它从来都不是绝对必要的。

浏览器中的 JavaScript 并不安全,因此不要做依赖于浏览器中的身份验证和授权的事情。

我在这里写了一篇关于其中一些的小文章:http: //lostechies.com/derickbailey/2012/01/26/modularity-and-security-in-composite-javascript-apps/

于 2012-06-06T20:11:35.220 回答