Next.js将api限制为我的Next.js应用程序和我的移动应用程序



让我澄清一下我的用例:

我有一个next.js应用程序,它是一个用于列出房地产对象的平台。我在next.js应用程序中使用了几个api路由。例如:

/api/createpost -> 

在我的next.js应用程序上从我的表单中获取信息,并创建一个数据库条目来执行新的后

/api/getposts -> 

从我的数据库中获取所有的房地产帖子并将其显示为

/api/login -> 

通过检查数据库中的凭据登录用户,并发送jwt

/api/register -> 

通过从我的next.js应用程序的表单中获取凭据来注册用户,注册用户并在我的数据库中创建条目


现在,为了保护我的api,如果有人正在调用其中一个api(注册/登录api除外)以获得预期结果,我想确保检查是否存在有效的用户会话。我通过调用/api/login路由并获得一个有效的用户会话来实现这一点。在这里之前一切都很好。只有当我们有一个有效的用户会话时,才能调用像/api/createpost这样的Api。

现在我想创建一个移动应用程序,我也想使用上面的api路由在我的移动应用程序中提供完整的功能。它应该同样工作,例如,如果我想在我的手机应用程序上调用/api/createpost,我需要一个有效的用户会话。

但我想通过在我的数据库中询问指向我的应用程序的密钥来限制我的api,并说如果你调用/api/createpostapi,可以,首先我需要验证它是否是移动应用程序的请求。移动应用程序将在请求中提供密钥。

我还没试过这个,但我认为它应该有效现在大混乱:如果我们调用/api/createpost,而api想要一个有效的令牌来检入数据库,这对移动应用程序来说是有效的,因为我们给了它一个有效令牌来检查数据库,如果我们从next.js应用程序内部调用api,我们如何提供令牌?由于我必须在客户端进行api调用,因此我无法提供密钥或其他东西来验证调用是否来自我的next.js应用程序

如果您的应用程序是私有的

(仅供您或少数选定人员使用)您可以通过SSL将API私钥与应用程序中的每个请求一起发送到服务器并进行验证。也可以将API限制为仅接受来自特定IP的请求。

如果您的申请是公开的

不幸的是,无法确定请求的来源,因为你的应用程序可以发送任何内容,攻击者都可以手动发送
考虑一下,如果您的应用程序试图向API发出请求,任何用户都可以在该请求从他/她的机器发送之前拦截该请求,并从同一机器上的不同应用程序发送完全相同的请求

你可能会说,我可以加密请求和响应,这样攻击者就不会使用它们了。但这样的加密需要一个已经达成一致的密钥,或者在每次会话开始时以某种方式提供新的密钥。

  1. 如果密钥已经达成一致,则应用程序必须包含该密钥,正如您在问题中已经猜到的那样,无论您如何隐藏该密钥,攻击者都可以检索该密钥
  2. 如果加密密钥是在每个会话开始时提供的新密钥,SSL几乎就是这样工作的,那么浏览器将处理此事务。您的服务器会向浏览器发送一个公钥来加密请求,然后服务器可以使用私钥对其进行解密。在这种情况下,您又回到了同一个问题,如何验证您向谁提供了加密密钥?怎样才能阻止攻击者请求加密密钥

必须有某种方法可以设计不需要此限制的应用程序我认为你应该问的不是如何将你的api限制在某个应用程序上,而是如何设计不需要这种限制的应用程序如果你能告诉我们你为什么需要这个限制,我们可能会帮助你。


更新

实际上,有一种方法可以验证请求是否来自您的应用程序,但不能使用api密钥。

对于Web应用程序
您可以使用Google的reCAPTCHA验证/register和'/login'路由上的用户,并在成功的captcha响应后提供访问令牌或启动有效的用户会话。使用reCAPTCHA v3,您甚至可以在不中断用户的情况下验证每个用户操作。这消除了我在上面的回答中提到的两个问题-

  1. 您不必将api密钥存储到应用程序/web应用程序中
  2. 该请求不能被欺骗,因为它需要在您的应用程序中进行人工用户交互。captcha验证成功将从Google的reCAPTCHA服务器而不是从您的客户端应用程序到达您的API。此通信将使用Google向您共享的预先中介的专用API密钥进行身份验证,其工作方式与您对外部域进行身份验证的方式相同

对于Android应用程序

实现相同目的的类似方法是通过Android SafetyNet验证API。这将检查运行时环境,并使用您的应用程序为SafetyNet API提供的动态生成的nonce对响应进行签名。请仔细阅读其文档,以了解如何在使用此API时创建潜在的安全漏洞以及如何避免这些漏洞。

对于iOS应用程序
DeviceCheck的工作方式类似,只是设备有效性由苹果服务器提供。

重要编辑:"有担保";这里用的词不对您不能仅仅因为域是您的域就认为请求来自您的应用程序。域名不是一个安全的信息,因为它很容易被更改。请参阅下面的@Mythos评论。


初始答案:

Web应用程序的访问不是基于API密钥,而是基于域的白名单。这就是我们实现安全的方式,因为只有您才能访问托管自己应用程序的域:因此请求必须来自您自己的应用程序。

如果你尝试一些为网络应用程序提供API的第三方服务,它们通常就是这样工作的:它们会让你配置一组可以访问你的数据的白名单域。如果他们为您提供了一个API密钥,那么这个API密钥总是用于服务器,而不是客户端应用程序。

所以,如果我正确理解你的问题,你会为每个请求这样做:

  1. 检查域。如果它在白名单中,那么完美,你可以继续前进。这是针对网络应用程序的(查找"CORS")
  2. 如果不是,请在标头中检查有效的API令牌。这适用于任何可以安全存储此API令牌的应用程序(例如,另一台服务器,或者您场景中的移动应用程序,尽管我对移动设备的了解不够,无法告诉您如何存储这样的密钥)

相关内容

最新更新