背景:
我正在为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 API客户机。除非您使用TLS客户端身份验证,否则SSL本身并不是REST API的可行身份验证机制。没有客户端authc的SSL仅对服务器进行身份验证,这与大多数REST api无关,因为您实际上需要对客户端进行身份验证。
如果不使用TLS客户端身份验证,则需要使用类似基于摘要的身份验证方案(如Amazon Web Service的自定义方案)或OAuth 1.0a,甚至HTTP基本身份验证(但仅通过SSL)。
这些方案验证请求是由预期的人发送的。TLS (SSL)(不需要客户端身份验证)确保通过线路发送的数据保持不被篡改。它们是相互独立但又相互补充的问题。
对于那些感兴趣的人,我已经扩展了一个关于HTTP身份验证方案及其工作原理的SO问题。
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的影响。)