2

我一直在阅读 API 通信证券并试图找出构建安全 API 的最佳方法。我知道存在 OAuth 等,但我也在尝试在此过程中自我教育,而不是依赖库。

基本上我有一个 Web 服务,并且在该 Web 服务中用户可以注册 API。他们将获得一个配置文件 ID 和密钥,他们必须使用它们来构建来自另一个 Web 系统的 API 请求。

API 请求的构建方式与银行类似,所有发送到 API 的输入数据都必须进行排序,计算哈希值,然后将哈希值发送到服务器,如下所示:

// Profile data
$apiProfile='api123';
$apiSecret='this-is-a-good-day-to-be-a-secret-key';

// Input
$input=array();
$input['name']='Thomas Moore';
$input['profession']='Baker';

// To ensure that the order of variables checked and received is the same on both ends:
ksort($input);

// Using serialize() for simplifying things
// http_build_query() is another option, or just placing values in order
$input['hash']=sha1(serialize($input).$apiSecret); 

// Making a request to URL:
// Using file_get_contents() as an example, would use cURL otherwise
$result=file_get_contents('http://www.example.com/api.php?'.http_build_query($input));

// SERVER CALCULATES COMPARISON HASH BASED ON KNOWN SECRET KEY AND INPUT DATA

这真的很好并且有效。但!我的问题是潜在的重放攻击。如果有人窃取了这个请求 URL,他们可以再次将其发送到服务器,即使他们无法更改数据本身。

现在我已经阅读了一些关于它的内容,您还应该检查时间或在请求中添加一次性使用令牌,但我不确定我应该怎么做?发送带有请求的时间戳真的足够安全吗?(如果时钟有点同步,接收服务器将确保请求是在发出请求的几秒钟内发出的)。

我还可以添加 IP 验证,但这些可能会发生变化,并且可能会受到一定程度的欺骗,并且给用户带来更多麻烦。

我会喜欢这种一次性令牌类型的系统,但我不确定如何在不将令牌生成暴露于完全相同的重放攻击问题的情况下做到这一点?(我需要的最后一件事是允许为中间人提供安全令牌)。

非常欢迎意见和文章,我一直无法找到回答我的具体问题的材料。我想说我的 API 是安全的,而不仅仅是市场营销。

谢谢!

4

2 回答 2

3

您只需要允许通过安全通道 (https) 进行令牌交换,并且每条消息都应该有一个唯一的哈希值。包括时间戳和客户端的 ip 等内容。如果您不使用 https,那么您很容易受到火羊式攻击。

除此之外,您正在正确地进行令牌生成和交换。

于 2012-03-29T18:18:45.873 回答
2

发送时间(并将其包含在缓存中)确实是一种选择。

当您第一次请求会话令牌或会话密钥时,另一个选项是两阶段算法,然后将其用于会话,并且其 TTL 存储在服务器上(可以是时间或允许的请求数)

至于会话密钥的想法,请查看http://en.wikipedia.org/wiki/Diffie%E2%80%93Hellman_key_exchange之类的方案

1-time token 算法示例:

1) 客户端对 1-time 令牌进行请求,使用密钥对该请求进行签名并将其发送到服务器。

2)服务器生成密钥,用相同的密钥签名并发送给客户端(连同签名)

3) 客户端使用密钥验证令牌

4) 客户端组成请求,包括令牌,并用密钥对整个请求体进行签名,然后发送到服务器

5)服务器检查整个主体完整性和令牌有效性,然后发送响应(再次可以使用密钥签名以进行完整性和作者身份验证)

于 2012-03-29T18:17:23.137 回答