SPA的简单API认证方案
Posted
技术标签:
【中文标题】SPA的简单API认证方案【英文标题】:Simple API authentication scheme for SPA 【发布时间】:2017-10-13 23:32:10 【问题描述】:我正在为具有单个 REST API 后端的 SPA Web 应用程序寻找一种简单的身份验证方案。
要求是:
-
针对自定义凭据存储的身份验证(应该足够灵活);
在指定的空闲超时后自动注销用户;
尊重最佳安全实践。
目前的想法:
-
使用 HTTPS;
创建身份验证 API 端点;
SPA 会将用户凭据传递给身份验证 API 端点;
如果验证成功,上述 API 端点会以令牌响应(JWT,包括:用户 ID、可选用户 ID 版本;已将过期时间设置为现在 + 允许的空闲超时);
SPA 将令牌存储在浏览器本地存储中;
此后 SPA 在所有 API 请求的标头中都包含令牌;
所有受保护的 API 端点验证提供的令牌并从中提取用户 ID;
SPA 跟踪令牌的过期时间,当它接近时,SPA 向身份验证 API 端点发送续订请求(不包括凭据,仅包括当前令牌);
身份验证 API 端点处理续订请求并使用新令牌或 401 状态代码进行响应。
我预计这种方法有以下好处:
-
简单 - 需要 2 个后端组件(身份验证 API 端点和令牌验证/解析实用程序)+ 3 个 SPA 组件(登录、刷新、将令牌插入请求标头);
灵活性 - 令牌仅包含标识声明,它不以任何方式限制访问控制实现,也不限制底层身份验证方案;
不需要会话 - 无需查询会话存储,这可能对性能有好处;
使单个用户令牌无效的能力 - 可以通过增加(或更改)用户存储中的用户 ID 版本来实现。
所以问题是:
我错过了什么? 这个方案有什么缺点吗?
【问题讨论】:
【参考方案1】:为什么 JWT 可能不适合您的用例的一些反驳观点:
在指定的空闲超时后自动注销用户;
由于 JWT 令牌是不可变的,因此您无法检查用户空闲了多长时间(因为您无法检查上次操作的时间)
也没有撤销令牌的“好方法”。可能的方法是:
使用较短的过期时间(用户必须经常重新登录) 保留已撤销令牌的黑名单(基本上是您提出的,但您的应用程序不会是无状态的) 更改密钥(但这会使所有用户的所有现有令牌无效)--他们都有自己的缺点。
不需要会话 - 不需要查询会话存储,可能它 对性能有好处;
使单个用户令牌无效的能力 - 可以通过在用户中增加(或更改)用户 ID 版本来实现 商店。
如果您的应用程序是无状态的,这对性能会有好处,但这样做会将状态保留在用户存储中。
【讨论】:
关于 在指定的空闲超时后自动注销用户 - 在提议的方案中,它是使用“滚动”令牌实现的:令牌的生命周期相对较短(1 - 10 分钟) , SPA 必须经常更新它们。如果 SPA 不更新令牌,它将过期并发生注销。 关于 sessions 和 statelessness - 在用户帐户中有一种版本字段不会使后端 有状态 - 它仍然不跟踪会话。但它允许后端在各种情况下采取不同的行动:对于大多数 API 端点来说,仅验证令牌和提取用户 ID 就足够了;对于特定的 API 端点(例如,令牌更新期间的身份验证 API 端点),需要验证令牌、提取用户 ID 并将用户 ID 版本与用户存储进行比较。 关于无状态 - 无状态编程与函数的数学概念有关,当使用相同的参数调用该函数时,总是返回相同的结果。这是函数式编程范式的一个关键概念——因此,如果您将用户 ID 保存在数据库中并将其与令牌中的用户 ID 进行比较,则它不是无状态的。您实际上是将状态存储在服务器上。 关于滚动令牌 - 这可以工作,但安全将是一个问题。如果有人设法窃取访问令牌,他可以让它永远活着吗?虽然我想这可以解决(即有最大数量的续订) 关于无状态 - 即使我选择使用用户名作为用户 ID?因为在这种情况下,它是一个普通的 JWT,据我所知,它被认为是无状态的。以上是关于SPA的简单API认证方案的主要内容,如果未能解决你的问题,请参考以下文章