11

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

会话和密码验证

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

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

会话存储

当然, Redis很棒。会话存储很简单,并且会自动进行垃圾收集。不幸的是,redis 中的会话很难管理:我无法轻易撤销给定用户的所有会话。通过将会话存储在真正的 redis 数据结构而不是全局键空间中来添加该功能会消除添加键控 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在 express 响应时最终设置 cookie,这不是所需的行为。

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

API 密钥

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

扩展和开放标准

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

另一个问题是自定义 HTTPAuthorization标头是否是一个好主意,或者自定义标头是否是一个更好的主意。

CRUD 支持

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

TLDR

两件事情:

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

2 回答 2

8

如给定的那样,这个问题是无法回答的。会话状态。因此,您不能无状态地实现会话。

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

如果您确实需要会话,但不想在 Cookie 标头中传输状态令牌,则应使用OAuth机制,该机制允许使用 Authorization 标头或请求参数来保存协商的状态令牌。

我们确实希望创建一个框架,在其中添加上述标准很简单

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

于 2014-01-09T14:07:43.417 回答
2

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

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

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

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

于 2014-01-09T14:40:32.583 回答