无需对移动应用进行用户身份验证即可保护私有 REST API 的最佳方法

Posted

技术标签:

【中文标题】无需对移动应用进行用户身份验证即可保护私有 REST API 的最佳方法【英文标题】:Best way to secure Private REST API without user authentication for mobile app 【发布时间】:2015-03-30 20:16:08 【问题描述】:

我正在为我的移动应用程序制作一些 Restful API。

APP 和 webserver 之间的通信必须在 REST 中进行。这些 api 应该是私有的,并且只有我的应用程序才能调用它们以获得成功的结果。

困难的部分是,我的应用程序中不需要用户 ID 和密码,所以我不知道如何在没有基本用户身份验证的情况下使用移动应用程序限制 rest API。

我认为的一个解决方案是嵌入某种硬编码字符串,这样当移动应用程序使用 restful url 时,它们会以加密格式通过 ssl 传递它。但我知道这似乎是非常糟糕的解决方案..

请提出在这种情况下最好的解决方案。

【问题讨论】:

***.com/questions/6134082/… 您可以从讨论中看到,您所要求的几乎是不可能实现的。我们可以验证用户,而不是应用程序。唯一可能的方法是某种共享秘密。但是,如果您的客户端应用程序能够进行逆向工程,那么它就不安全并且一无所获。 谈到逆向工程,没有什么能与之抗衡。然而,很容易让他们的工作越来越难。如果我以一些复杂的数学公式/函数的形式嵌入我的秘密呢? 听起来不错,如果有人以数学公式的形式制作他的密钥,并根据来自服务器和客户端的一些值生成密钥。 【参考方案1】:

你确实可以让逆向工程师的工作变得更难,但不能像Nasir 所说的那样,通过引入数学难题并相应地转换你的硬编码字符串来使其变得无懈可击。

这个怎么样。假设在应用程序中硬编码一个数字A。服务器发送两个数字BP(P 是一个大素数)。现在您可以使用(A^B) % P 计算将由服务器验证的实际数字。您的应用现在使用Server's Public Key 加密(A^B)%P 的答案。服务器将使用其私钥对其进行解密,对其进行验证,并发出一个带有过期时间的令牌(可能是 jwt)。然后您的应用程序和服务器可以使用该令牌进行通信。您可以在应用启动时执行一次计算并存储令牌以供进一步使用。

【讨论】:

【参考方案2】:

您说得对,应用程序中的嵌入式密钥可以通过数据包嗅探器或各种其他技术轻松检索。您可以使用以下说明解决此问题。

客户端(您的应用)将调用所需的 API 服务器会拒绝它,但作为响应它会发送一个包含随机哈希的字符串 (=challenge)。 客户端将该字符串与其他字符串(=密码)(已嵌入应用程序)结合使用以生成新的哈希(=摘要) 客户端将再次调用相同的 API,但这次使用新创建的摘要作为身份验证参数。 服务器将验证该摘要并继续进行

仅供参考:上述程序是被广泛接受的标准,被称为Digest Authentication。如果您需要更多帮助,请向 Google 询问“android http 摘要身份验证”

【讨论】:

我认为这很好,但添加公钥和私钥加密可以使其更安全。 同意!我认为摘要式身份验证非常容易实现,并且还提供了足够的安全性。但是,如果您对自己的 APP 如此谨慎,那么您绝对应该使用基于密钥的加密通信。 仍然可以检查移动应用程序以找到其他字符串 (=password)。【参考方案3】:

看看基于哈希的消息验证码 (HMAC) 机制。

***链接:http://en.wikipedia.org/wiki/Hash-based_message_authentication_code

您的客户端(移动应用程序)将需要一个标识 REST Web 服务客户端的 公共 API 密钥和一个 私有 / 加密 密钥。公共 API 密钥可以与 HTTP 请求一起发送。它是公开的,每个人都可以看到。但是,私钥不应该与请求一起发送,并且应该只被服务器和客户端知道。此密钥用于生成散列消息,然后将其发送到服务器。 HMAC 可以使用 SHA1 / MD5 算法生成,该消息应该由服务器和客户端都知道的算法生成,最后是私钥。

【讨论】:

但我有一个问题,您是否建议我应该将私钥嵌入移动应用程序的代码中,因为它不是浏览器。我实际上不明白如果我输入代码我应该在哪里保存我的私钥,那么如果有人能够对其进行逆向工程怎么办。我认为这种方法可以将我从嗅探数据的间谍中解救出来。 是的,你是对的。如果您将私钥存储在代码/配置文件中,那么就有机会,我认为不可能使其防弹。但是,您可以使事情变得更难。我对常用技术不是很熟悉,但看看这个问题:***.com/questions/8184492/…。希望对您有所帮助!【参考方案4】:

我建议在应用程序中创建一个复杂的令牌,由时间戳 + appId + 您可以在服务器上复制的任何其他值组成,并使用这些值在每个请求的标头中进行身份验证。

例如,您可以在数据库中创建一个虚拟“用户”并将 deviceToken 存储在其中并将其用于您的算法。

我个人公开了一个 API 请求,它是时间戳获取器,它返回服务器的时间戳以在 300 秒内使用。

所以在每个请求之前,获取时间戳,并发送您创建的令牌,将其复制到服务器上,从而对请求进行身份验证。

一个平庸的黑客可以对应用程序进行逆向工程并复制您的令牌

【讨论】:

以上是关于无需对移动应用进行用户身份验证即可保护私有 REST API 的最佳方法的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 OAuth2 身份验证保护私有数据?

无需手动输入凭据即可进行 SSO 身份验证

如何通过 Wordpress REST API 对 LearnDash 中受保护数据的远程访问进行身份验证?

Flutter:Firebase身份验证无需登录即可创建用户

我可以在 phpmyadmin (XAMPP) 中禁用 mysql 保护允许访问而无需任何身份验证吗?

移动应用程序 + REST 后端中的 OpenID Connect 身份验证流程(使用 KeyCloak)