【发布时间】:2016-11-25 14:14:08
【问题描述】:
我们正在迁移基于 MVC 的服务器应用程序并制作一个 REST-ful API,通过该 API 处理调用。
我一直在阅读有关 AES 加密和 OAuth2 的信息,并决定实施一个从这些概念发展而来的解决方案,如下所示:
- 客户端发送请求以提供用户 ID 或电子邮件登录。此请求使用 API 密钥进行 HMAC 处理。
- 服务器检查用户 ID/电子邮件是否与现有帐户匹配,如果找到,则创建并存储一个服务器随机数,并将其作为响应的一部分发送给客户端。
- 客户端创建自己的客户端随机数,并根据 API 密钥和两个随机数创建一个新的临时密钥。然后它会发送一个登录请求,其中包含使用此临时密钥加密的密码[为了增加熵并避免以明文形式发送密码]。
- 服务器使用它在此平台上为此客户端存储的最新随机数解密密码和 HMAC [移动客户端和 Web 客户端可以有自己不同的随机数和会话] 以及以明文形式发送的客户端随机数,如果 HMAC 签出,则根据数据库验证密码 [PBKDF2 散列和加盐]。
- 如果请求有效并且密码和用户 ID 匹配记录,则在该平台上为该用户 ID 创建一个新的会话密钥,并将此密钥发送到客户端,并将用于 HMAC 来自客户端的每个 API 请求今后。
- 任何新的非登录请求都将包含根据会话密钥和随机 IV 计算得出的 HMAC 签名。
所有通信都通过 TLS 处理,因此这是增加了安全性,而不是唯一的防线。
在移动应用程序上这会起作用,因为您可以在配置文件中隐藏移动应用程序的密钥,这提供了一些不错的安全措施 - [也许不是很多,我不完全确定] 但是如果我们尝试转换从我们的网页到此表单的所有请求,这意味着使用 Javascript 来处理客户端 AES 加密和身份验证以及...well as this article clearly explains,“如果您将 API 密钥存储在 JavaScript Web 应用程序中,您不妨打印它在主页上以粗体大字显示,因为全世界现在都可以通过浏览器的开发工具访问它。”
我可以只使用随机数作为 API 密钥——或者完全放弃对这些请求使用 AES 加密,并尝试通过其他方式进行验证,例如 CSRF 令牌,并确保所有请求都来自我们自己的前端方式 - 但如果我们想创建一个允许与其他页面或服务集成的 API,那么这将行不通,即便如此,我将如何保护客户端的秘密会话密钥?
文章建议生成一次性 cookie 作为令牌,但这是一个有限的解决方案,适用于发布者的服务,但不适用于我们。我希望能够使用可以过期和重置的用户特定密钥对用户发送的每个请求进行 HMAC,并且由于服务最终会处理资金,因此我希望严格锁定请求身份验证。
那么我有什么选择?
因为它is doomed,我是否就放弃了 Javascript?是否有某种方法可以存储密钥,而不会像硬编码到 .js 脚本中那样清楚地暴露它?我是否应该生成一个仅用于登录调用的新临时密钥,并在用户请求服务器 nonce 时将其发送给用户?
另外,我链接到的帖子首先建议使用 cookie 来存储客户端的会话密钥,然后从 JS 访问密钥。这样可以吗,还是会提供比密封更多的孔?
【问题讨论】:
标签: javascript oauth-2.0 aes