如何在没有SSL的Web API上接受身份验证?

时间:2010-12-22 13:31:47

标签: security api authentication

我正在构建一个非常类似于StackOverflow提供的Web API。

但在我看来,安全性非常重要,因为数据是私有的。

  • 我必须使用HTTP。
  • 我无法使用SSL。

你推荐我什么解决方案?

编辑:身份验证!=加密

4 个答案:

答案 0 :(得分:17)

几乎每个公共API都通过为每个Web请求传递身份验证令牌来工作。

此令牌通常以两种方式之一分配。

首先,一些其他机制(通常登录到网站)将允许开发人员检索永久令牌以在其特定应用程序中使用。

另一种方法是根据请求提供临时令牌。通常,您有一个网络方法,他们会在其中传递用户名/密码,并根据经过身份验证和授权执行任何API操作的情况返回有限使用令牌。

在dev拥有令牌后,他们会将其作为参数传递给您公开的每个Web方法。您的方法将在执行操作之前首先验证令牌。

作为旁注,你对“安全性很重要”的评论显然不是真的。如果是,那么你将通过SSL执行此操作。

我甚至不认为这在任何情况下都是“最小”的安全性,因为它只是提供了一种错误的信念,即你有任何安全性。正如皮斯科夫指出的那样,任何有兴趣的人都可以以某种方式倾听或打破这一点。

答案 1 :(得分:16)

首先,我建议你阅读这篇优秀的文章:http://piwik.org/blog/2008/01/how-to-design-an-api-best-practises-concepts-technical-aspects/

解决方案非常简单。它是Flickr API(基于令牌)和我使用的paiement gateway使用的身份验证方法(高度安全)的组合,但是使用私人密码/盐。

为了防止未经授权的用户使用API​​而不必在请求中发送密码(在我的情况下,由于没有SSL而明确),他们必须添加签名,其中包含私有和公共值的串联的 MD5哈希

  • 众所周知的值,例如用户名甚至API路径
  • 用户密码短语
  • 用户生成的唯一代码(只能使用一次)

如果我们要求 / api / route / 且密码短语为 kdf8 * s @ ,则签名如下:

string uniqueCode = Guid.NewGuid().ToString();
string signature = MD5.Compute("/api/route/kdf8*s@" + ticks);

HTTP请求的URL将是:

string requestUrl = 
     string.Format("http://example.org/api/route/?code={0}&sign={1}", uniqueCode, signature);

服务器端,您必须使用相同的唯一代码阻止任何新请求。防止任何攻击者简单地重复使用相同的URL。这是我想避免的情况。

由于我不想存储API使用者使用的代码,我决定用 ticks 替换它。刻度表示自0001年1月1日午夜12:00:00起经过的100纳秒间隔的数量。

在服务器端,我只接受刻度(时间戳),容差为+ -3分钟(如果客户端和服务器没有时间同步)。意味着潜在的攻击者将能够使用该窗口来重用URL但不能永久使用。安全性有所降低,但对我的情况仍然足够好。

答案 2 :(得分:6)

简短回答:如果它应该可以通过普通客户端使用(浏览器请求/ AJAX),那么你就搞砸了。

只要您使用未加密的传输,攻击者就可以通过MITM攻击删除任何类型的页内加密代码。即使SSL也不能提供完美的安全性 - 但普通的HTTP需要一些页外特定的扩展。

HTTP仅提供传输 - 没有安全标识,没有安全身份验证,也没有安全授权。

示例安全漏洞 - 一个简单的HTTP页面:

<script src="http://example.com/js/superstrongencryption.js"></script>
<script>
  encryptEverything();
</script>

这可能看起来很安全,但它有一个重大缺陷:您没有任何保证,根本,您实际上正在加载您要求的文件superstrongencryption.js 。使用普通HTTP,您将发送请求某处某些内容返回。没有办法验证它实际来自example.com,也没有办法验证它实际上是正确的文件(而不仅仅是function encryptEverything(){return true})。

也就是说,理论上你可以在你的HTTP请求和响应中构建非常类似于SSL的东西:对每个请求进行加密加密和签名,与每个响应相同。你需要为此编写一个特殊的客户端(当然还有服务器端代码) - 它不适用于标准浏览器。

答案 3 :(得分:1)

HTTP digest authentication提供了非常好的身份验证。我用过的所有HTTP客户端库都支持它。它根本不提供任何加密。