我正在构建一个API,并正在尝试在多种情况下确定身份验证。
会话和密码认证
API需要为我们创建和部署的客户端应用提供服务,并使用密码处理已认证的请求。将密码与每个请求一起发送不是一个好主意,因此更合理的方法是首先访问登录端点并获取会话ID。相关的Web应用程序是使用AngularJS编写的,并应在localStorage中跟踪自己的会话,以减轻会话劫持并删除对cookie的会话跟踪依赖。
Web应用程序需要在每个请求中发送会话标识符,目前将其放在请求正文中。这很容易导致分段,并且与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都希望在请求的不同部分(从正文到URL到标头)中接收API密钥。
扩展性和开放标准
虽然我们不打算在初始发布时支持OpenAuth和OpenID等开放认证标准,但我们希望创建一个框架,使添加此类标准变得简单明了。其中一部分可以是统一授权凭据交给API的方式,就像会话/密码和API密钥支持的身份验证一样。
另一个问题询问是否自定义HTTP Authorization
标头是一个好主意,还是使用自定义标头更好。
CRUD支持
为了支持RESTful API的CRUD范例,不应在正文中提供身份验证信息,因为这将限制所有API请求为POST请求,而CRUD建议使用各种HTTP方法。
总结
两件事:
- 如何在不使用基于cookie的会话的情况下使用像connect-redis这样的模块。
- 我们应该如何配置身份验证信息以实现最大的灵活性和互操作性?
https://username:password@yourdomain.com/api/path?query=string
;您的路由处理程序将测试凭据并根据需要加载用户数据和/或会话数据。 - Plato