Node.js无状态/无Cookie会话API身份验证

时间:2013-10-15 18:27:12

标签: node.js session authentication cookies express

我正在构建一个API并尝试在许多上下文中找出身份验证。

会话和密码验证

API需要为我们创建和部署的客户端应用程序提供服务,并使用密码处理经过身份验证的请求。对每个请求发送密码并不是一个好主意,因此首先点击登录端点并获取会话ID更有意义。有问题的webapp是用AngularJS编写的,应该在localStorage中跟踪它自己的会话,以减轻会话劫持并消除对cookie的依赖以跟踪会话。

webapp需要在每个请求中发送会话标识符,并且当前在请求正文中这样做。这很容易碎片,并与API紧密结合。我宁愿以一种方式通过标题传递所有身份验证信息,最好是 - 而不是遍布请求正文,网址和标题的许多不同字段。

会话存储

当然,

Redis很棒。会话存储很简单,并自动进行垃圾收集。不幸的是,redis中的会话很难管理:我不能轻易撤销给定用户的所有会话。通过将会话存储在真正的redis-datastructure而不是全局键空间中来添加该功能会删除添加键控TTL的功能。我目前的解决方案是在MongoDB用户集合中存储会话列表,并在会话活动(例如登录/注销)上垃圾收集过期的会话。

会话以connect-redis模块的形式存储在redis中,但随着每个请求发送它们都不包含在cookie中。目前,我有一小块中间件,它将会话标识符从请求主体中取出并放入req.cookies对象。

var express = require('express');
var RedisStore = require('connect-redis')(require('connect'));

var app = express();
app.use(function(req, res, next) {
  req.cookies = {session: req.body.session};
});
app.use(express.session({
  store: new RedisStore({
    client: redisClient,
    prefix: 'session:'
  }),
  key: 'session',
  secret: 'all mine'
});

这种方法很好,除了express.session在表达响应时最终设置cookie,而这不是理想的行为。

如何在Express的上下文中正确设置?

API密钥

我们的API还应支持第三方应用程序的API密钥,以获得对我们系统的有限和受控访问。我所知道的最常见的机制是将API密钥分发给感兴趣的开发人员,并让开发人员在请求中传递API密钥。这会遇到会话/密码身份验证遇到的相同困境:每个API都要求API密钥位于请求的不同部分,从正文到网址到标题。

扩展和开放标准

虽然我们不打算在初始版本中支持OpenAuth和OpenID等开放式身份验证标准,但我们希望创建一个框架,其中添加所述标准非常简单。其中一部分可能是统一授权凭证如何传递给API,如会话/密码和API Key支持的身份验证。

Another question询问是否自定义HTTP Authorization标头是一个好主意,或者自定义标头是否更好。

CRUD支持

为了支持RESTful API的CRUD范例,不在身体中提供身份验证信息是有意义的,因为这会将所有API请求限制为POST请求,而CRUD建议使用各种HTTP方法。

TLDR

两件事:

  1. 我们如何在不使用基于cookie的会话的情况下使用connect-redis之类的模块。
  2. 我们应该如何配置身份验证信息以获得最大的灵活性和互操作性?

2 个答案:

答案 0 :(得分:8)

如上所述,这个问题是无法回答的。会话状态。因此,您无法无状态地实施会话。

如果你真的想要无状态身份验证,那么你就不能拥有会话,你应该使用HTTP Authentication机制。

如果你真的想要会话,但是你不想在Cookie标头中传输状态标记,那么你应该使用OAuth机制,它允许使用Authorization标头或请求参数来保存协商状态令牌。

  

我们希望创建一个框架,其中所述标准的添加是直截了当的

最简单,最好的方法是使用它们开始。不要重新发明轮子。 OAuth2旨在在多个用例中轻松实现,并且如果您需要更多,它还有自己的扩展机制。

答案 1 :(得分:2)

您可以考虑通过基于令牌的方法来完全不使用会话。

您可以使用至少包含用户ID和到期日期以及服务器密钥的哈希生成加密令牌。在登录请求中验证用户后,您甚至不需要包含密码。

令牌将在Authorization标头中传递,避免使用cookie或任何其他请求参数。

使用此令牌,您可以识别用户并检查到期日期,而无需在服务器端存储,因此没有会​​话状态。如果您需要根据需要使经过身份验证的令牌过期,您只需要一个商店。