我正在构建一个非常类似于StackOverflow提供的Web API。
但在我看来,安全性非常重要,因为数据是私有的。
你推荐我什么解决方案?
编辑:身份验证!=加密
答案 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 / 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客户端库都支持它。它根本不提供任何加密。