背景:
我正在为REST Web服务设计身份验证方案.这并非"真正"需要安全(它更像是一个个人项目),但我希望尽可能安全地将其作为锻炼/学习体验.我不想使用SSL,因为我不想要麻烦,而且主要是设置它的费用.
这些SO问题对我开始特别有用:
RESTful身份验证
保护REST API/Web服务的最佳实践
最好的SOAP/REST/RPC Web API示例?你为什么喜欢他们?他们有什么问题?
我正在考虑使用简化版的Amazon S3身份验证(我喜欢OAuth,但它似乎对我的需求来说太复杂了).我正在为请求添加由服务器提供的随机生成的nonce,以防止重放攻击.
要回答这个问题:
S3和OAuth都依赖于对请求URL进行签名以及一些选定的标头.他们都没有签署 POST或PUT请求的请求体.这是不是容易受到中间人攻击,它会保留url和header并用攻击者想要的任何数据替换请求体?
看起来我可以通过在被签名的字符串中包含请求主体的哈希来防止这种情况.这样安全吗?
之前的回答仅在数据传输的上下文中提到了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.其他任何东西都会有点时髦,需要为客户提供额外的部署工作,这些工作必须有可用的加密库.
一旦你提交SSL,原则上认证真的没什么需要的.您可以再次使用Web标准并使用HTTP Basic auth(与每个请求一起发送的用户名和密钥令牌),因为它比精心设计的签名协议简单得多,并且在安全连接的上下文中仍然有效.你只需要确保密码永远不会超过纯文本; 因此,如果通过纯文本连接接收密码,您甚至可以禁用密码并邮寄开发人员.您还应该确保在收到凭据时不会记录凭据,就像您不记录常规密码一样.
HTTP摘要是一种更安全的方法,因为它可以防止秘密令牌传递; 相反,它是服务器可以在另一端验证的哈希.虽然如果采取上述预防措施,对于不太敏感的应用可能会有些过分.毕竟,用户的密码在登录时已经以纯文本形式传输(除非您在浏览器中进行了一些奇特的JavaScript加密),并且每个请求都使用了他们的cookie.
请注意,使用API时,客户端最好传递令牌 - 随机生成的字符串 - 而不是开发人员登录到网站的密码.因此,开发人员应该能够登录您的站点并生成可用于API验证的新令牌.
使用令牌的主要原因是,如果它被泄露,它可以被替换,而如果密码被泄露,所有者可以登录开发者的帐户并用它做任何他们想做的事情.令牌的另一个优点是您可以向同一个开发人员发出多个令牌.也许是因为他们有多个应用程序,或者因为他们想要具有不同访问级别的令牌.
(更新以涵盖仅使SSL连接的含义.)
或者您可以使用已知的解决方案来解决此问题并使用SSL.自签名证书是免费的,它是个人项目吗?
如果您需要正文的哈希值作为URL中的参数之一,并且该URL是通过私钥签名的,那么中间人攻击只能用生成内容的内容替换正文.相同的哈希.现在至少可以轻松处理MD5哈希值,当SHA-1被破坏时,你就可以了解情况.
为了防止身体被篡改,你需要一个身体的签名,这样一个中间人攻击不太可能破坏,因为他们不会知道产生签名的私钥.