背景:

我正在为REST web服务设计身份验证方案。这并不“真的”需要安全(这更像是一个个人项目),但我想让它尽可能安全,就像一个练习/学习经验一样。我不想使用SSL,因为我不想要设置SSL的麻烦,主要是不想要设置SSL的费用。

这些SO问题对我的开始特别有用:

宁静的身份验证 保护REST API / web服务的最佳实践 最好的SOAP/REST/RPC web api的例子?你为什么喜欢它们?他们有什么问题?

我正在考虑使用简化版的Amazon S3身份验证(我喜欢OAuth,但对我的需求来说似乎太复杂了)。我在请求中添加了一个由服务器提供的随机生成的nonce,以防止重放攻击。

回到这个问题:

S3和OAuth都依赖于对请求URL和一些选定的头进行签名。它们都不为POST或PUT请求签名请求体。这难道不容易受到中间人攻击吗?中间人攻击会保留url和头部,并用攻击者想要的任何数据替换请求体。

似乎我可以通过在签名的字符串中包含请求体的散列来防止这种情况。这安全吗?


当前回答

或者您可以使用这个问题的已知解决方案并使用SSL。自签名证书是免费的,它是个人项目,对吗?

其他回答

REST意味着使用web标准,而web上“安全”传输的标准是SSL。其他任何东西都有点古怪,需要额外的客户端部署工作,客户端必须有可用的加密库。

Once you commit to SSL, there's really nothing fancy required for authentication in principle. You can again go with web standards and use HTTP Basic auth (username and secret token sent along with each request) as it's much simpler than an elaborate signing protocol, and still effective in the context of a secure connection. You just need to be sure the password never goes over plain text; so if the password is ever received over a plain text connection, you might even disable the password and mail the developer. You should also ensure the credentials aren't logged anywhere upon receipt, just as you wouldn't log a regular password.

HTTP摘要是一种更安全的方法,因为它可以防止秘密令牌被传递;相反,它是服务器可以在另一端验证的散列。如果您已经采取了上面提到的预防措施,那么对于不太敏感的应用程序可能会过度使用。毕竟,用户的密码在登录时已经以明文形式传输了(除非您在浏览器中进行了一些花哨的JavaScript加密),同样,他们的cookie也会在每次请求时传输。

注意,对于api,最好是客户端传递令牌——随机生成的字符串——而不是开发人员登录网站时使用的密码。因此,开发人员应该能够登录到您的站点并生成可用于API验证的新令牌。

使用令牌的主要原因是,如果它被泄露,它可以被替换,而如果密码泄露,所有者可以登录到开发人员的帐户并对其进行任何操作。令牌的另一个优点是可以向相同的开发人员发出多个令牌。也许是因为他们有多个应用程序,或者因为他们想要具有不同访问级别的令牌。

(已更新,以涵盖使连接仅ssl的影响。)

事实上,原始的S3身份验证允许对内容进行签名,尽管使用的是弱MD5签名。您可以简单地强制他们在HMAC(要签名的字符串)中包含Content-MD5头的可选实践。

http://s3.amazonaws.com/doc/s3-developer-guide/RESTAuthentication.html

他们新的v4认证方案更加安全。

http://docs.aws.amazon.com/general/latest/gr/signature-version-4.html

或者您可以使用这个问题的已知解决方案并使用SSL。自签名证书是免费的,它是个人项目,对吗?

前面的回答只提到了数据传输上下文中的SSL,实际上并没有涉及身份验证。

您实际上是在询问如何安全验证REST API客户机。除非您使用TLS客户端身份验证,否则SSL本身并不是REST API的可行身份验证机制。没有客户端authc的SSL仅对服务器进行身份验证,这与大多数REST api无关,因为您实际上需要对客户端进行身份验证。

如果不使用TLS客户端身份验证,则需要使用类似基于摘要的身份验证方案(如Amazon Web Service的自定义方案)或OAuth 1.0a,甚至HTTP基本身份验证(但仅通过SSL)。

这些方案验证请求是由预期的人发送的。TLS (SSL)(不需要客户端身份验证)确保通过线路发送的数据保持不被篡改。它们是相互独立但又相互补充的问题。

对于那些感兴趣的人,我已经扩展了一个关于HTTP身份验证方案及其工作原理的SO问题。

如果您需要主体的哈希作为URL中的参数之一,并且该URL是通过私钥签名的,那么中间人攻击只能用生成相同哈希的内容替换主体。至少现在用MD5哈希值很容易做到,当SHA-1被破坏时,你就知道了。

为了确保主体不被篡改,您将需要主体的签名,中间人攻击不太可能破坏这个签名,因为他们不知道生成签名的私钥。