有没有办法保护前端页面上的 API 密钥?
Posted
技术标签:
【中文标题】有没有办法保护前端页面上的 API 密钥?【英文标题】:Is there a way to secure an API key on a frontend page? 【发布时间】:2019-02-25 22:00:21 【问题描述】:我的服务允许使用 POST 请求将任何 html 文档转换为 PDF。 它主要用于我的客户端服务器的后端,因此用于通信的 API 密钥是保密的。
现在,我正在考虑一种方法,让我的客户的访问者能够代表我的客户端 API 密钥调用我的服务,而不会暴露这个安全的 API 密钥。
我的主要问题是安全性。如果我的客户添加了一个包含 API 密钥的 XHR POST 请求,那么有人可以获取该 API 密钥并将其用于自己的目的并滥用我客户的帐户。
我可以按域进行过滤,但是这很容易被欺骗,所以这是不可能的。
我想知道是否有一种方法可以从客户端(的客户端)调用私人服务并在不冒其身份被盗的风险的情况下进行识别?
【问题讨论】:
您的客户能否在其前端提供基于时间的一次性密码,您可以在后端进行验证?有点像 csrf 令牌 您不能创建新的visitorsKey
,它将与访问者用来代表客户进行通信的客户密钥相关联吗?这样,一旦您获得此visitorsKey
,您就可以识别客户。他们也没有客户的密钥。
【参考方案1】:
如果您为经过身份验证的用户提供此 sublet,那么为他们提供唯一密钥(根据 API 密钥和初始时间戳对他们的用户 ID 或会话进行哈希处理,并检查/记录/查找)是相当简单的在访问 API 之前进行暴力破解)。如果你在开放的网络上进行,没有任何类型的用户身份验证,那么速率限制确实会变得非常棘手。通常,您希望使用会话哈希、IP 地址、操作系统和浏览器数据的组合来创建一个匿名配置文件,该配置文件在前端获取一个临时密钥。一种相当可靠的方法是在提供临时密钥之前强制用户通过验证码,以允许他们有限次数地使用永久密钥。任何其 ip/浏览器/会话与已知客户端密钥的现有属性匹配的用户都会被分流到那个用户(并跳过验证码);任何与现有个人资料不匹配的人都会获得验证码。这使您成为欺骗目标的吸引力降低。最重要的是,您应该始终根据您期望(或负担得起)的流量类型,将整个事情的速率限制在合理的每天点击次数内,这样您就不会有任何意外。如果每次使用他们的 API 密钥时客户的钱都在线,这是您想要的最低限度的安全性。它将需要一个简单的数据库来存储这些“配置文件”、跟踪使用情况、检查暴力并维护当前有效的客户端密钥。客户端密钥应始终定期过期 - 与创建时间的时间差异,或常规的 cron 进程,或最大使用次数等。
我经常做的另一件事是基于曲线的速率限制。例如,如果我认为每分钟使用 5 次是合理的,那么在会话一分钟内使用 5 次后,每次使用都会增加几分之一秒的延迟 * 数据前最后一分钟的使用次数,平方已送达。
最好的答案是将这一切都放在登录系统后面并保护那个。
【讨论】:
验证码的想法对于未经身份验证的用户来说真的很有趣(不幸的是我的情况)【参考方案2】:假设您使用的是 OAuth 类型的系统,在这种情况下,请使用访问令牌机制,该机制代表用户(客户端)提供对私有 API/用户数据的访问,而不会暴露他/她的凭据或 API 密钥(身份验证key),访问令牌也可以根据时间/使用情况过期。
示例:访问令牌是针对单个端点生成的,该端点可以是 Html 转换端点,一旦操作完成就会过期。
https://auth0.com/docs/tokens/access-token
以下博客文章将有助于构建您的身份验证系统 https://templth.wordpress.com/2015/01/05/implementing-authentication-with-tokens-for-restful-applications/
【讨论】:
【参考方案3】:没有做前端安全存储的好方法,但我的建议是:
是一个将请求的 HMAC 签名与 OAuth 身份验证结合使用的 API。 API 密钥实际上是一个签名密钥。他们的密钥不会被转移。 API 密钥仍然可以在前端找到,但它变得无用,因为您仍然需要 OAuth 令牌来发送有效请求。
我知道用户必须登录,但您可以将此视为一个优势,因为您至少可以通过从 oauth 获取信息来记录谁在使用该应用程序。
请考虑后端安全存储!
【讨论】:
感谢您的意见。我有一个完整的后端安全存储,问题是我的一些客户希望能够在前端完成所有工作。这就是我问的原因:) 是的..所以我的问题;)【参考方案4】:在我看来,您可以使用 JWT 令牌。根据用户名、密码或任何其他信息,您可以为不同的用户生成唯一的 jwt 令牌。 任何人都可以破译这些 jwt 令牌,但不能破译他唯一的安全令牌。
如果您想为令牌添加更多安全性,请使用 JWE,加密的 Web 令牌。
有关这些方案的更多信息,请访问https://medium.facilelogin.com/jwt-jws-and-jwe-for-not-so-dummies-b63310d201a3
【讨论】:
【参考方案5】:散列是一个不错的选择,无论如何都应该这样做,但是对于不会增加太多复杂性的完全安全的方法,您可以通过构建自己的 API 来与 API 交互,从而简单地从授权/API 密钥中抽象出来.这样,您既可以限制可以使用 API 密钥完成的事情的种类,也可以完全隐藏用户的 API 密钥
【讨论】:
【参考方案6】:我认为您不应该总是选择用户身份验证或 JWT,它只是不适合所有用例。使用验证码的想法很有趣,但也有些复杂。
如果复杂性不是问题,我宁愿使用基础设施方法,因为我对 AWS 最熟悉,所以我将重点介绍这一点。假设您可以更改前端的主机,您可以将您的站点托管在 S3 存储桶上,通过 CDN 提供服务,并创建一个代理 Lambda 函数,该函数将保存调用您的 API 的逻辑并将 API 密钥存储为加密环境多变的。您通过 API 网关调用的此 Lambda 只能由 S3 存储桶也使用的特定 IAM 角色调用。您也可以使用 Cognito 用户池而无需身份验证。
回到更简单的替代方案,Captcha 方法可以实现为证明提供程序。我知道有两种服务可以做到这一点,Firebase 和 KOR Connect。由于在撰写本文时 Firebase 仅将这种方法用于他们自己的资源,我更愿意使用 KOR Connect,因为它是一个非常简单的中间件,基本上可以解决这个问题。我不会详细介绍这些服务,因为这不是本主题的主要关注点,但您可以查看文档各自的链接。
【讨论】:
以上是关于有没有办法保护前端页面上的 API 密钥?的主要内容,如果未能解决你的问题,请参考以下文章