我在决定如何为RESTful API实施身份验证时遇到一些麻烦,这些API对Web应用和移动应用都是安全的。
首先,我考虑通过HTTPS调查HTTP基本身份验证作为选项。它适用于移动应用程序,其中用户名和密码可以安全地存储在操作系统密钥链中,并且由于请求将通过HTTPS而无法在传输过程中被截获。 API也很优雅,因为它完全是无状态的。这个问题是针对Web应用程序的。将无法访问用于存储用户名和密码的密钥链,因此我需要使用cookie或localStorage,但随后我将用户的私人详细信息存储在易于访问的位置。
经过更多的研究,我发现了很多关于HMAC认证的讨论。我用这种方法看到的问题是需要一个只有客户端和服务器知道的共享秘密。如何在Web应用程序中为特定用户获取每个用户的秘密,除非我有一个api / login端点,它接受用户名/密码并将秘密返回存储在cookie中?在将来的请求中使用。然而,这是向API引入状态。
要将另一个扳手投入工作,我希望能够将API限制为某些应用程序(或者,能够阻止某些应用程序使用API)。我看不出网络应用程序是完全公开的,这是怎么回事。
我真的不想实施OAuth。这对我的需求来说可能有些过分。
我觉得我可能不会完全理解HMAC,所以我欢迎解释以及如何使用网络应用和移动应用安全地实施它。
我最终使用HTTP Basic Auth,但是不是每次请求都提供实际的用户名和密码,而是实现了一个端点来交换访问密钥的用户名和密码,然后为每个经过身份验证的请求提供。消除了在浏览器中存储用户名和密码的问题,但当然如果您有权访问该计算机并使用它,您仍然可以删除令牌。事后看来,我可能会进一步研究OAuth,但对初学者来说这很复杂。
答案 0 :(得分:22)
您应该使用OAuth2。方法如下:
1)移动应用
移动应用程序存储您自己声明的客户端凭据。然后使用"资源所有者密码凭证授予" (请参阅http://tools.ietf.org/html/rfc6749#section-4.3)发送这些凭据。反过来,它获得了一个(承载)令牌,可以在以下请求中使用。
2)网站
该网站使用"授权码授予" (见http://tools.ietf.org/html/rfc6749#section-4.1):
网站看到未经授权的请求,并将浏览器重定向到REST API中支持HTML的自动化终端。
用户使用REST服务进行身份验证
REST网站将用户重定向回网址,并在网址中显示访问令牌。
网站调用REST网站并将访问令牌交换为授权令牌。
此后,网站使用授权令牌(代表最终用户)访问REST服务 - 通常通过将令牌包含为" bearer" HTTP授权标头中的令牌。
这不是火箭科学,但确实需要一些时间来完全理解。
3)限制某些应用程序的API访问
在OAuth2中,每个客户端都会获得一个客户端ID和客户端密钥(此处为#34;客户端"是您的移动应用程序或网站)。客户端必须在授权时发送这些凭据。您的REST服务可以使用它来验证调用客户端
答案 1 :(得分:2)
解决API用户身份验证问题的一种方法是在用户登录时从API请求身份验证令牌。然后,此令牌可用于后续请求。你已经触及过这种方法 - 听起来很不错。
关于限制某些网络应用程序。您希望每个Web应用程序都能识别每个请求,并在API实现中执行此身份验证。很直接。
答案 2 :(得分:2)
我非常轻松,安全地解决了这个问题,而无需公开任何客户端凭据。
我还将问题分成两部分。 API身份验证 - 这是来自已识别实体(网站或本机应用程序)的有效请求。 API授权,是允许使用此特定端点和HTTP谓词的实体。
使用访问控制列表以及根据需要在API代码,配置和数据库中设置的用户权限和设置,将授权编码到API中。 API中的简单if语句可以测试授权并返回相应的响应(未授权或处理API调用的结果)。
现在,身份验证只是检查呼叫是否为正版。为此,我向客户发出自签名证书。只要他们想要,就可以从他们的服务器调用API - 通常是在他们生成第一页时(或者当他们执行自己的应用程序登录检查时)。此调用使用我之前提供的证书。如果在我这边我很高兴证书有效我可以返回一个nonce和一个限时生成的API密钥。此密钥用于所有后续调用其他API端点,例如,在承载标头中,它可以非常公开地存储在HTML表单字段或javascript变量或应用程序中的变量中。
nonce将阻止重播攻击,如果有人想要,API密钥可能会被盗 - 他们在过期后无法继续使用,或者nonce在下次呼叫之前发生变化。
如果nonce不匹配,每个API响应将包含下一个nonce,它将返回一个身份验证错误。实际上nonce不匹配我也杀了API密钥。这将强制真正的API用户使用证书重新进行身份验证。
只要最终用户保持这些证书的安全,并且不公开他们用来进行初始身份验证调用的方法(比如使它成为可以重放的ajax请求),那么API就很好而且安全。