编写安全的REST Web服务

4

很多人对如何编写安全的REST Web服务感到困惑,对于那些不确定使用哪种方法的人来说,本文将大有裨益。

编写REST服务的可能方式(部分安全)

  • 你意识到直接通过HTTP传递凭据会让这些数据以明文形式被窃取;在Gawker事件之后,你意识到明文或弱哈希任何东西通常都是一个坏主意。

  • 你意识到哈希密码并发送哈希而不是明文密码仍然会向窃听者透露至少账户用户名和密码的哈希值,这些哈希值在(令人不安的)许多情况下可以在彩虹表中查找到。

  • 你大声喊道,因为在这种情况下(实际上又是一个用户名/密码场景),你仍然面临着与以明文形式发送用户名和密码相同的问题(被窃听的流量)。

  • 此时,你即将放弃并承认使用OAuth,但你坚持认为必须有一种既安全又相对简单的方法来设计一个可以保护凭据私密的公共Web API。


不要通过HTTP传递凭据,使用HTTPS。 - NoChance
他们中的许多人是谁?难道只有我错过了这个问题吗? - Roman Vottner
1个回答

4

最佳方案

一个服务器和客户端知道公钥和私钥,只有服务器和客户端知道私钥,但任何人都可以知道公钥……谁在乎他们知道了什么。 一个客户端通过组合请求数据(参数和值或XML / JSON或计划发送的任何内容)并将请求数据块与私钥一起哈希来创建表示其向服务器发出请求的唯一HMAC(散列)。 然后客户端将该HASH与它打算发送的所有参数和值一起发送给服务器。 服务器获取请求并基于提交的值使用与客户端相同的方法重新生成自己的唯一HMAC(散列)。 然后服务器比较两个HMAC,如果它们相等,则服务器信任客户端并运行请求。

示例解释: (假设您从Android发送此请求,由于Android应用程序大多数是无会话的,因此无法具有cookie或任何记住哪个用户已登录。因此对于这种情况,发送请求时还需要用户凭据。)

  • 要进行请求的网站(在本例中我使用localhost): localhost:8080/
  • 用户X的URL REST请求: localhost:8080/REST/books/favorites (假设响应以逗号分隔的纯文本形式返回[哈利波特,月亮杂志,无限思维,暮光之城])。
  • 由于要显示用户X信息,因此请求将类似于此: localhost:8080/REST/username/Password/books/favorites-localhost:8080/REST/X/abc/books/favorites

这里的问题是用户名和密码可以被嗅探到,因为它们是明文...所以最好在客户端加密它们,在服务器端解密它们。

  • 解决此问题的方法是生成URL请求的散列并将该散列添加到URL的末尾,然后将请求发送到服务器。(通常我们说的是校验和)...使用您自己的散列生成器或使用基于Java的散列生成器,如SHA1,MD5等来生成校验和

  • 假设为URL请求生成的哈希值 localhost:8080/REST/encrypted-username/encrypted-Password/books/favorites 是一些哈希字符串adasfsjimnom123123k。因此,请将其添加到您的URL中

localhost:8080/REST/encrypted-username/encrypted-Password/books/favorites/adasfsjimnom123123k

这样,您可以保护Web服务请求的安全性。只有在生成的校验和有效时,服务器才提供所请求的详细信息。

使用Curl工具作为REST消费客户端(而不是单独的Java代码)来测试您的服务。

完整参考


1
您的服务器可以验证哈希是否正确,因为它拥有客户端用于生成哈希的私钥。您最初是如何在客户端和服务器之间交换私钥的? - 2020
1
这个解决方案听起来不错。但是在解释中公钥和私钥并不清楚。看起来两者使用同一把密钥。在一些情况下这应该不是问题。 - Ton Snoei

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接