用于客户端-服务器通信和安全的 api-key
Posted
技术标签:
【中文标题】用于客户端-服务器通信和安全的 api-key【英文标题】:api-key for client-server communication and security 【发布时间】:2016-07-05 17:23:37 【问题描述】:我需要一些建议。 我想构建一个 JS 应用程序,它将在客户端浏览器上运行并与我的服务器与 ajax 通信。 问题是我想给这个客户端一些 api-key,这样我就可以在我的服务器上授权它。 安全方面是个问题,因为只要此密钥通过 ajax 调用发送,任何人都可以复制此调用。 我不想让客户端创建一些代理服务器并“卷曲”请求。 我希望它直接从客户端到我的服务器。 除了通过 IP 或域验证客户端之外,最佳实践是什么?
【问题讨论】:
AJAX 不能跨域。 JSONP 是另一回事。 @CharlotteDunois orly?什么是 CORS? @CharlotteDunois Orly? Yarly :D 你错了。样式表、图像甚至脚本等静态文件本身就是跨域的。引入 CORS 是为了允许 AJAX(又名 XmlHttpRequest)的跨域请求。 @CharlotteDunois 例如,当您对任何 Google Maps API 资源执行请求时,您的浏览器将首先执行带有动词 OPTIONS 的请求以获取所需的 CORS 标头,因此实际请求可以通过以下方式完成 -通过默认同源策略 重复? ***.com/questions/15496915/… 【参考方案1】:遗憾的是,您只能检查 Referer
标头,并使用允许的引用者白名单颁发 API 密钥。
这里的主要问题是Referer
根本不安全:它可以更改。也就是说,任何人都可以冒充客户......
AFAIK,重点是您的客户应该能够重新创建他们的 API 密钥,并且一旦他们意识到有人在冒充他们,他们就应该这样做。他们应该不断地重新重新创造,直到坏人停止冒充他们......
尽可能的努力...
让冒充实际客户端的不需要的客户端更难处理的一种可能方法是使用具有过期时间的访问令牌。
此外,一个好的做法是一个客户每天可以请求有限数量的访问令牌。如果这些访问令牌有 24 小时的到期时间,并且每个 API 密钥每天限制为 3 或 4 个访问令牌,如果许多坏人试图冒充您的客户之一,那么,只有3 就能做到。
您还可以定义每天访问令牌的限制。这可能会使事情变得更加困难。
顺便说一句,您可以争辩说任何人也可以窃取整个访问令牌。好吧,现在是重新生成 API 密钥并获取新密钥的时候了。最后,这些坏人会厌倦让他们的访问令牌失效......
最佳解决方案
实际上,如果您的 API 需要安全并且它是私有的,正如您在某些 cmets 中对我自己的回答所说的那样,这里别无选择:您需要采用服务器代理方式 .
我会检查 node-oauth2-server 以使用 OAuth2 来保护您的 API。
【讨论】:
所以它仍然没有帮助。如果我检查 ip 或域,它是否足够安全?就像我想要一个域白名单并检查服务器上的引荐来源网址。 Hacers 可以复制这个请求吗? @PazLazar IP 也可以修改...您可以确定最好的办法是努力使事情变得困难,但没有办法 100% 确定您的 API 将被期望和实际消费者 @PazLazar 我的建议也是谷歌等知名公司的设计决策。他们的 Maps javascript API 就是这样工作的……API 密钥和你一样是公开的,你可以配置允许的引荐来源,并且每天的请求有配额限制…… 你必须明白——我不想尝试和限制——我必须。这不是我可以限制并让坏人努力工作的一些天气或地图 api。存储在服务器上的数据非常私密,我的客户不能让任何人看到它。因此为客户端生成一些令牌将无济于事,也不使用引荐来源网址。我唯一能做的就是要求客户端使用服务器代理生成令牌,这是我在第一次调用时给他的 api-key,然后在下次调用时使用这个令牌...... @PazLazar 我已经明白这一点,但您要求避免使用请求代理...如果您想要一个 99% 安全的系统,那么您必须这样做。顺便说一句,有些人可以模仿一些网站或 HTTP 客户端,只是将请求粘贴到 Fiddler 或 Postman 之类的东西中,并使用整个访问令牌。如果您没有在浏览器中存储访问令牌,那么任何人都可以通过某些客户端站点从 Fiddler 或 Postman 向您的 API 发出请求............【参考方案2】:你可以使用JWT之类的东西。
您创建一个身份验证对象
apiKey: asd-dfgdf-e3234, // not even necessary (read on)
expires: 12213493434,
ip: "x.x.x.x"
您对其进行 base64 编码,然后使用私钥(或服务器上的哈希函数)对其进行签名,并将签名作为 base64 字符串附加到“有效负载”。
eyBhcGk6IDEyMzQ1LTU2Nzc4LCBhcGk6IDEyNy4wLjAuMSB9.Tm90IFNlY3VyZSE=
| -------- payload ----------------------------| -- signature -|
将此传递给您的客户。每个请求都会发送此令牌。可以对其进行检查和验证以防篡改(无需密钥即可匹配请求的 IP)。
【讨论】:
它没有帮助,因为如果我可以用 JS 加密它,任何其他黑客都可以解密它,甚至更糟 - 只是使用它...... 你没有加密它。你签字。您获取 base64 文本并在您的服务器上签名。除非黑客拥有您的私钥,否则该“哈希”目前不可逆。黑客可以尝试修改令牌,但在服务器上快速检查(此有效负载签名是否有效)将揭示伪造。如果有效,则检查 IP 与请求 IP 以确保它们匹配。 @Wainage 顺便说一句,这还不够......源IP地址也可以被模拟............ 您实际上是在向客户发送身份证。如果黑客拦截它,您的服务器将在 IP 或签名上失败,您将能够知道他们正在使用其他人的 ID @Matias IP 不能被模拟。这会将流量发送到其他地方。如果您的意思是中间人攻击,那么我希望您使用的是 https ...否则您所有的秘密都属于 NSA。以上是关于用于客户端-服务器通信和安全的 api-key的主要内容,如果未能解决你的问题,请参考以下文章