PHP RESTful API 安全

标签 php api security hmac

我目前正在用 PHP 构建一个 RESTful API,它将用于支持网络和移动应用程序。因此,API 应被视为公开的。但是,我想在用户从移动设备或 Web 向 API 发出请求时对其进行身份验证。

当用户注册该服务时,我会生成一个唯一的 API key 和 secret ,这些 key 和 secret 存储在数据库中的用户记录中。理想情况下,我希望使用 JavaScript 或 PHP 仅使用 API key 发出请求。

想到建立一个握手系统进行认证,流程如下:

  • 用户使用他们已知的 key 向 API 发出请求。
  • API 以 token 响应,该 token 连同时间戳一起存储在表中(以防止重放攻击)
  • 然后客户端使用 token 发出实际请求,API 将检查 token 的有效性。如果哈希匹配且时间戳有效,则 API 提供有效响应,否则提供 token 已过期的信息。

我正在考虑使用 HMAC 生成 token ,如下所示:

$token = hash_hmac('sha256', $user->apiKey.microtime(), $user->apiSecret);

$token 将存储在数据库中,并且对于每个请求都应该是唯一的。然后可以使用以下 jQuery 代码依次发出请求:

$.getJSON('/api/user/get/1', { 'key': '123rrwfnufsd7f72' }).done(function(data) { 
    // data will now contain a token, so we use it to make another AJAX request:
    if( data.token )
    {
        $.getJSON('/api/user/get/1', { 'token': data.token }).done(function(user) {  
             // do something with user or handle bad token
        });
    }
});

我的问题是这是否足以防止暴力破解和重放攻击?

最佳答案

我刚刚创建了一个关于这个的小库。如果需要,您可以指定以分钟为单位的时间漂移​​,甚至可以使用自定义盐。 (参见 https://github.com/gboddin/psk-validator/)

此库允许您验证来自客户端的签名消息 使用基于时间的盐。

安装

composer require gboddin/psk-validator

用法

客户端

$sharedsecret = '43223ff65b6ce17072cda5729b20daceec611d1f39e76040d347ceeca51d2a47';
$data = json_encode(['suff','otherstuff',['machin' => 'bidule']]);

/**
 * Client :
 * Invoke the validator with the pre-shared key and an algo  (sha256 by default) and
 * define an allowed time drift in minutes ( 2 by default ).
 */
$sigValidation = new \Gbo\PSKValidator($sharedsecret, 'sha256');
/**
 * Signs a bunch of data and get the signature.
 * The second optional parameters allows for a user provided salt instead
 * of the default time based salt. It must be agreed on between client and server.
 */
$signature =  $sigValidation->sign($data, null);

服务器

/**
 * Server :
 * The optional third parameter allows to define a maximum time drift  in minutes ( default 2 minutes )
 */

$signature =  $httpRequest->getHeader('x-signature');
$sharedsecret = '43223ff65b6ce17072cda5729b20daceec611d1f39e76040d347ceeca51d2a47';
$sigValidation = new \PSKValidator($sharedsecret, 'sha256', 2);
$data = $httpRequest->getBody();

/**
 * Server :
 * The third optional parameters allows for a user provided salt instead
 * of the default time based salt. It must be agreed on between client and server.
 */

$signatureIsValid = $sigValidation->verify($data, $signature, null);

var_dump(
    $data,
    $signature,
    $sigValidation->getTimeBasedSignatures($data),
    $signatureIsValid
);

服务器输出

string(41) "["suff","otherstuff",{"machin":"bidule"}]"
string(64) "d85a2d6873e034cb3ab8c490cb82139d8dabae6c08581cca0a2e7497ead287a4"
array(5) {
  [0]=>
  string(64) "d85a2d6873e034cb3ab8c490cb82139d8dabae6c08581cca0a2e7497ead287a4"
  [1]=>
  string(64) "dc150239c61fe272b7ca44ad0918d159a84e5bc1661db48bad04a81bc7f4c742"
  [2]=>
  string(64) "e1822fc6cc7bbf1184b29efaaaceac6d598fb406b4f8cf9b3717b3d0c533c19f"
  [3]=>
  string(64) "d85a2d6873e034cb3ab8c490cb82139d8dabae6c08581cca0a2e7497ead287a4"
  [4]=>
  string(64) "d85a2d6873e034cb3ab8c490cb82139d8dabae6c08581cca0a2e7497ead287a4"
}
bool(true)

(对不起 self 推销:))

关于PHP RESTful API 安全,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42435095/

相关文章:

asp.net - 如何显示更好的错误然后:"A potentially dangerous Request.Form value was detected from the client"

security - 在 iframe 中设置 cookie - 不同的域

java - 识别 java keystore 中的条目

php - 如何使用php从mysql数据库中获取所有匹配的记录?

php - Symfony @ParamConverter : exclude the use if the placeholder does not contain a dot

php - SQL 语句超出 PHP 中的最大时间,但在 phpMyAdmin 中立即运行

c# - MVC - 如何从 URL 请求并保存 pdf 文件

javascript - 谷歌云端硬盘 API : ENOENT - but my file is just in the same directory

php - 正则表达式从 URL 中提取文件扩展名

java - 在 Java 后端和 Android 应用程序之间共享 POJO