在Javascript Web应用中保护私有API密钥

8

如何在基于Web的(JavaScript)应用程序中安全地存储私有API密钥?

我已经做了彻底的研究,但仍未找到可靠的答案或任何标准程序。

我的API实现了HMAC身份验证,我的网站每个成员都有一个公共/秘密密钥来验证他们对API的使用并签署请求。

在移动应用中,服务器会通过加密连接发送公共/秘密密钥以便在成功登录请求后存储在设备上。随后的请求将使用这些密钥进行签名。

那么,在此情况下应该在客户端存储密钥,考虑到源代码对于知道如何使用Web检查器的任何人都是可见的?实际上,如果经过身份验证的用户看到自己的密钥,则不是问题,因为他们不太可能与其他人分享它们,就像他们不太可能与其他人分享帐户用户名/密码一样。


可能的解决方案?

将公共/私密钥存储在Cookie中,并使用JavaScript检索 - 可能不太安全,当用户注销/会话结束时,Cookie是否可以可靠地清除?

将公共/私密钥存储在网页本身中 - 我能想到的唯一真正的解决方案 - JavaScript可以通过DOM访问密钥,只有在用户保持登录状态且其他人知道在哪里查找它们时,它们才会被泄露(看到)。

注意: Web应用程序不是单页面应用程序,因此将公共/私有键存储在内存中不是一个选项。


我不确定自己是否走上了正确的轨道(有些事情告诉我没有),希望有人可以为我指引正确的方向。

谢谢

3个回答

1
我得出结论,我在这里试图保护自己免受CSRF攻击的影响。
我使用laravel进行开发,所以我的解决方案是在头部添加csrf nonce(Session::token()) 如此看来
<meta name="token" content="32947fh2834fgkhgfr8724234f">

并将其作为请求头一起发送:

$.ajaxSetup({
    headers: { 'session_token': '32947fh2834fgkhgfr8724234f' }
});

在授权API请求时,需要检查“session_token”标头并验证其真实性。如果没有session_token,它将回退到HMAC检查。

结合SSL应该足够了,你有什么想法?


0

我不确定是否有明确的解决方案。听起来你试图在浏览器中存储一个“秘密”?即使你试图混淆它,总会有一种查看它的方法。


我想是的。我开始认为用户以某种方式揭示自己的密钥并不那么危险。但关于在哪里存储密钥,使得除授权用户之外的任何人都无法看到它们的问题仍然存在。 - user3202641
@thomasfw 你能够尽力保证的是将机密安全地传递给目标(即浏览器)。一旦它们到达那里,所有的赌注都取消了,因为这完全取决于客户端如何保护他的计算机。如果机器感染了恶意软件,那么你就很惨了。 - deceze
@deceze你有什么建议?将公钥存储在cookie中,将私钥存储在文档的某个位置(类似于如何在表单内生成nonce)如何?<div id="keys" data-secret="{{api_secret}}"></div>。我无法相信没有这方面的程序,Facebook是如何验证其API的站点请求的? - user3202641
据我所知,公钥/私钥在浏览器中并不常用。Facebook等通常使用短暂的令牌,即传统的会话ID。至少这些令牌可以与客户端绑定,并采用多项附加的合理性检查(如IP、运行计数器、浏览器标头)进行吊销。 - deceze
@deceze 那么也许解决方案是为我的API设置两个授权程序 - 这样我可以从移动/编译应用程序发送HMAC签名请求,或者绕过此过程并确认如果在标头中收到有效令牌的请求?假定还使用ssl/tls加密连接将在防止令牌被破坏方面有所帮助? - user3202641

-1

您好,

在前端应用程序中使用API密钥和令牌始终需要安全地存储密钥或令牌,不幸的是,浏览器(客户端)没有这样的存储。可以通过在身份验证后使用访问令牌(如果是Oauth)而不是API密钥来克服此情况,并且这些访问令牌也可以具有自己的过期时间。

如果确实需要对客户端存储的密钥/令牌进行额外的安全保护,在这种情况下,我们将提出一种解决方案,例如使用基于base64的加密方法和某些哈希算法来加密我们的令牌,然后在API端点中进行解密和验证。

以下博客文章可能会对此有所帮助:

https://www.wolfe.id.au/2012/10/20/what-is-hmac-authentication-and-why-is-it-useful/


@v8-E,答案/解决方案已经以陈述的形式给出,链接仅供参考,不作为答案。 - Shahul Hameed
Base64不是加密,使用任何哈希算法时,令牌本身也无法恢复。此外,请在您的答案中添加所有澄清信息,而不是链接到外部资源。 - Nico Haase

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接