如何从客户端应用程序构建用户身份验证?


14

我一直在开发将支持许多用户的应用程序。问题是我不知道如何验证客户端/用户。

我正在构建一个http://quickblox.com/之类的应用程序,在该应用程序中我将向用户提供凭据,他们将使用这些凭据来构建N个应用程序,在这些应用程序中,他们无法输入用户名和密码来进行身份验证。

让我们假设它如下。(就像QuickBlox一样)

1.用户在我的网站上创建帐户。
2.用户可以创建N个API密钥和保密凭证。(对于多个应用程序)
3.用户将在其应用程序(Android,iOS,Javascript等)中使用这些凭据与我的REST API进行通信。
(REST API具有读写访问权限。)

我的顾虑?

用户会将其凭据(API密钥和秘密密钥)放入他们构建的应用程序中,如果有人获得了这些密钥并尝试模仿用户该怎么办?(通过反编译APK或直接查看JavaScript代码。

我在某处错了吗?
我对构建这种三级用户机制感到困惑。


您似乎想做的事情是不可能的。
user253751 '16

有许多应用程序可以完成相同的操作。我不确定他们如何验证用户身份。
阿罗克·帕特尔

您是否要对客户端应用程序用户进行身份验证?许多应用程序对用户进行身份验证。它们都不以不间断的方式对客户端应用程序进行身份验证。
user253751'8

是的,客户端,我的意思是我只想验证用户身份。
阿洛克·帕特尔

4
哦,好了,然后在最典型的身份验证系统中,您只需让用户输入其用户名和密码,然后将其安全地发送到服务器,服务器将对其进行检查,然后(安全地)返回一个会话令牌,然后将会话令牌发送到以后的每一个要求。
user253751'8

Answers:


7

过去几年,我一直在设计REST API。你太担心了 最近,该板上的另一个用户提出了一个问题,他担心在其中将URI端点存储在他的JavaScript客户端代码中

适用于您的规则与适用于JavaScript开发人员的规则相同。如果您允许外部人员集成您的API,则您的API具有与常规网站相同的可见性,因此您应该以相同的方式对待它。

引用原始答案:

当您创建网站时,您不希望用户做某事时,您不会实现该功能或禁止某些用户使用它。对于应该具有公共端点的REST API,它几乎是相同的,您需要将其视为公共网站。

您的REST API应该足够健壮,不允许出现无效操作,例如来自其他用户的数据访问。

您应将应用程序访问令牌设计为仅允许您要允许的操作。您可能有两种访问令牌:

  • 主令牌:可由应用程序创建者使用,并通过您的API提供更多功能,
  • 应用程序令牌:实际上将存储在应用程序中的令牌,仅具有对您的API的有限访问权限,只能访问不会破坏您或应用程序程序员的数据的操作。

但是,有人会解构源代码,将令牌从应用程序中取出,找出什么是公共端点并滥用您的Web服务?

除非您直接管理使用您的API的应用程序的开发,否则没有什么能真正阻止人们直接从该应用程序以相同的方式滥用您的API。


到目前为止,很好的解释,但是我有一个问题。比方说,我的API之一,是构建以获取所有的相关数据(A + B)我的用户我的用户在他的应用中使用此API只能获取其用户filtered data(B)。现在有可能,或者有什么解决方法可以防止第三位用户窃取我用户的所有数据(A + B)。是否有意义?
Alok Patel

@AlokPatel然后没有其他解决方法来简单地不实现该功能。当您这样做时,总是存在有人欺骗自己的身份哈希值使其看起来像其他人的风险。以编程方式,您的问题无法解决。正如我已经说过的,如果您不想提供某些功能,请不要实现它。由于应用程序很可能会在其中存储登录哈希,因此一旦部署了应用程序,您的API密钥也将随之公开,并且它不公开。
安迪

感谢您的解释。因此,到目前为止,我了解到REST API与我们部署的任何网站都是相同的,它们与网站一样开放。如果我不希望用户做某事,那么我根本就不会在我的REST API中实现它。因此,我可以做的是为客户端库(Android,iOS,JS)设置单独的密钥,这些密钥可能会因功能较少而受到损害,而不同的密钥将用于服务器端(PHP,Java,node.js),具有扩展功能。希望这会成功!
阿罗克·帕特尔

你能解释一下你的观点吗?除非您直接管理使用您的API的应用程序的开发
Alok Patel

@AlokPatel我的意思是,现在您担心让某人访问该API,他们可能会分发访问权限并开始滥用该API。如果您无法控制使用API​​的应用程序的开发,则它们甚至可以自行执行。
安迪

5

您的问题不是技术问题,而是业务问题。

假设您拥有自己的API,并且以每年100英镑的固定费率向客户(应用开发者)出售API,并且可以无限访问。

那么显然,我可以100英镑的价格购买您的服务,然后以50美元的价格将其出售给10个人。你不要那个!因此,您尝试考虑一种限制,该限制将允许您在不开放套利的情况下出售您的API。

  • 如果仅限制应用程序的数量,则客户可以创建一个应用程序,该应用程序接受来自其他应用程序的连接并将其继续传递。

  • 如果限制用户,客户又可以将用户隐藏在自己的身份验证后面,并且看起来像是一个用户。

您需要做的就是将每个API调用的费用转嫁给您的客户。例如,每个API调用收费,或设置每年的调用配额。

这给您的客户带来了同样的套利问题。它迫使他们采取措施以防止其用户窃取其密钥。在这种情况下,请将您的api隐藏在他们自己的用户身份验证的api之后。


我已经计划根据API调用的数量来限制我的API的使用,因此目前与我无关的问题是与业务相关的问题,我只担心密钥被盗。
Alok Patel

从业务角度来看,该问题是无法解决的。可悲的是,您也无法以编程方式解决它。
安迪

1
通过按每次呼叫收费来解决业务问题。如果钥匙被盗,您的客户就会迷失方向。不是你。只是给您的客户一种取消被盗密钥的方法,并向他们说要有一个防止滥用的中间api
Ewan,2016年

2

其他答案似乎都表明,无法解决在消费者设备上的应用程序中存储秘密的问题。

是的。

两个原则(具体实现方法如下):

  1. 实际的身份验证端点需要匿名向公众开放。
  2. 服务器必须以某种方式参与身份验证客户端和提供API密钥。

鉴于此,如果客户端使用凭据向身份验证端点发出请求,并且服务器对它进行身份验证,则服务器可以生成动态临时令牌(基于时间的临时含义)。该令牌应在客户端中记住,并与后续请求一起发送。

您需要一种机制来定期“刷新”令牌,即获得一个新令牌。只需构建一个REST端点即可允许从现有令牌生成新令牌,从而避免必须从凭据中重新进行身份验证。

如果您试图避免最终用户重新进行身份验证,则此身份验证可以在安装后作为应用程序中的初始一次性设置。

该解决方案完全避免了需要存储嵌入在应用程序二进制文件中的静态令牌的需求。只有响应成功的身份验证,服务器才会即时生成令牌。为了让恶意用户检查您的应用程序并尝试获得未经授权的API访问,他们仍然需要像其他任何人一样进行身份验证。


有趣的解决方案,尽管它主要取决于OP的客户如何编码其应用程序。这就是说,提出的方法可以允许随后存储API密钥服务器端,并且在对自己的用户进行成功身份验证之后,可以将临时密钥转发给实际的应用程序使用。这样,任何内容都不会存储在应用程序本身中。
Newtopian

所有API都是如此。如果API使用者未正确使用它,则可能无法正常工作。这必须是API的文档化部分。
布兰登

顺便说一下,像OAuth这样的标准可以帮助您更轻松地实现这一目标。
布兰登

0

如果您具有唯一的按应用程序唯一密钥,则只能在由客户端启动的初始连接身份验证期间使用这些密钥,然后切换到滚动式按应用程序唯一身份验证令牌。

您的服务器会不时更改(滚动)每个客户端应用程序的令牌(例如,定期加/减一些随机的模糊/随机延迟)。滚动令牌仅在服务器和经过身份验证的客户端之间是已知的。

新令牌将在常规回复中背负式地返回。每当答复中包含新令牌时,接收应用程序都需要切换为在后续请求中使用它。

每当与客户端的交换不同步(某种协议错误)时,您的服务器就会请求重新认证(通过对下一个客户端请求的错误回复,或piggy带在对客户端请求的有效响应上)例)。

客户端在主动使用滚动令牌时发起的初始身份验证应该引起怀疑-这很可能是模仿尝试。如果交换空闲超过预期的时间间隔(例如,这可能是由于客户端中断/使用没有滚动令牌的新实例重新启动)导致的,则我只会允许它。

最好将令牌保留在客户端,以便重新启动的客户端可以从其前身离开的位置继续-大大缩小了模仿的空间。

这种方案至少会使模仿变得非常困难-当授权客户端停止发送请求足够长的时间以使服务器决定可以接受具有指定密钥的新客户端身份验证时,模仿客户端将必须准确预测窗口。在允许的窗口之外的此类请求可以用作模拟尝试的检测,并可能启动一些对策(IP黑名单等)。


0

据我所知,您提到的是做到这一点的唯一方法。存储密钥的应用程序绝对有风险,但是可以通过多种方式来规避它。与硬编码相比,您始终可以使用密钥库来存储密钥,从而强制进行一次登录。

另外,您应该考虑将密钥绑定到客户端,因此,如果有人模仿,则应该具有安全层来检查客户端,密钥和用户代理以立即阻止请求。有一个用例来重新发行或确保密钥没有被模仿。


JavaScript的解决方法是什么?如何设计?
阿罗克·帕特尔

我假设您正在谈论创建混合应用程序。如果是这种情况,那么绝对应该可以创建一个插件来存储密钥。如果要托管应用程序并讨论移动Web解决方案,请考虑使用容器呈现页面,并且可以依靠之前建议的会话令牌
Arun

不,不是这样。我将成为第三大API提供者,我的用户将在他们的应用程序中使用我的API服务。它可以是Android,iOS,JavaScript等...
Alok Patel

0

如果您依靠向客户提供授权令牌来放入他们的应用程序,那么从理论上讲,总是有人可以对应用程序进行反向工程并提取它们。为防止这种情况,您需要一种不需要客户端应用程序内任何秘密的机制。那很棘手。我可以建议一些选项供您考虑。

一旦您给出了凭据,便会遇到问题,无法控制它们的存储安全性。另外,如果您要求用户将凭据发送给您,那么有人可以MITM您的连接并直接窃取令牌,而无需担心对应用程序进行反向工程。

使提取授权令牌更加困难的一种方法是混淆它。这只是提高了门槛,但并非不可能,要做到这一点,您就必须保留对秘密的控制权。您可以实现一个包含机密信息且特定于每个客户的库。您可以使用该库与服务器进行通信,甚至不必告诉用户秘密信息,也可以将其嵌入库中。这不能解决有人对您的库进行反向工程的问题,但是可以使您控制混淆的程度。缺点是,一旦一个人破坏了库中的混淆,除非您编写使每个库明显不同的代码,否则他们可以攻击您库中的任何库。这带来了自己的一系列问题。

这可能会偏离您的问题范围,但这与令牌的安全性有关,因此我将提及它。为了防止令牌通过网络被小偷,您可能不想直接发送令牌,而可以使用HMAC函数对流量进行签名。您可以通过在服务器上计算邮件的HMAC并将其与客户端发送的HMAC进行比较来检查邮件的有效性。您将使用令牌作为HMAC功能的密钥,以便只有知道令牌的人才能对流量进行签名。这对于令牌的安全性更好,因为您永远不会将其直接发送到服务器,因此无法直接对其进行拦截和窃取。有关HMACS的更多信息,请参见以下问题:https ://security.stackexchange.com/questions/20129/how-and-when-do-i-use-hmac/20301

没有任何安全解决方案是必不可少的,您必须确定实施该解决方案将花费多少成本以及遭到破坏的可能性和成本。


我无法创建一个库并在其中添加秘密,这对于我的每个用户而言都是不同的。
阿罗克·帕特尔

为了明确起见,我建议您可以为每个用户建立一个自定义库,并将他们各自的秘密隐藏在库中。您将需要编写一个系统来根据需要为每个新用户自动生成库,这可能比您想做的工作还要多。
ThePragmatist

0

报价自己:

我无法弄清楚如何对客户端/用户进行身份验证...在这种情况下,他们无法输入用户名和密码进行身份验证。

现在有点矛盾了,不是吗?;)

正如其他人所说,您不能。如果某个应用程序使用API​​密钥,则可以按照您所说的对它进行反编译,以获取并使用它。

除了要求额外的正确用户身份验证之外,您只能限制损坏:

  • 将IP列入白名单/黑名单
  • 节流
  • “异常活动”检测及其来源
  • 容易的密钥更新
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.