API 使用 HMAC 进行身份验证
API Authentication using HMAC
我正在寻找一种合适的身份验证方法,以便在编写用于我们内部系统的简单 API 时使用。 Stack Overflow 上的其他问题建议使用 HMAC 以及教程链接,我继续并决定实施这些链接。
设置之后,我意识到我不确定这对于实际身份验证有多重要。使用的教程 Here 在客户端列出了一个 public 散列,它从未在服务器端代码中使用过。它只是将 content 和 privateHash 值散列在一起,并在服务器上进行比较。由于这一切都通过 headers 传递,我想知道这实际上有多安全? public哈希值是多少,因为它似乎甚至没有被使用过?
客户:
<?php
$publicHash = '3441df0babc2a2dda551d7cd39fb235bc4e09cd1e4556bf261bb49188f548348';
$privateHash = 'e249c439ed7697df2a4b045d97d4b9b7e1854c3ff8dd668c779013653913572e';
$content = json_encode( array( 'test' => 'content' ) );
$hash = hash_hmac('sha256', $content, $privateHash);
$headers = array(
'X-Public: '.$publicHash,
'X-Hash: '.$hash
);
$ch = curl_init('http://domain.com/api2/core/device/auth');
curl_setopt($ch,CURLOPT_HTTPHEADER,$headers);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
curl_setopt($ch,CURLOPT_POSTFIELDS,$content);
$result = curl_exec($ch);
curl_close($ch);
echo "RESULT\n======\n".print_r($result, true)."\n\n";
?>
服务器
function auth()
{
$app = \Slim\Slim::getInstance();
$request = $app->request();
$publicHash = $request->headers('X-Public');
$contentHash = $request->headers('X-Hash');
$privateHash = 'e249c439ed7697df2a4b045d97d4b9b7e1854c3ff8dd668c779013653913572e';
$content = $request->getBody();
$hash = hash_hmac('sha256', $content, $privateHash);
if ($hash == $combinedHash)
{
$data = array('status' => "success");
response($data);
}
else
{
$data = array('status' => "failed");
response($data);
}
}
我认为您发布的文章以令人困惑的方式使用了术语 hash
。在文章中,$publicHash
是用户名,$privateHash
是用于对有效载荷进行签名的密钥。
换句话说,如文章所说,X-Public
header 的值应该用于从数据库中查询用户特定的密钥。然后使用此密钥从有效负载创建哈希。然后将此哈希值与 X-Hash
header.
的值进行比较
如果值匹配,那么您可以确定有效负载未被篡改and/or有效负载的发送者知道密钥。
这种方法不是无状态的。它要求您为每个请求访问数据库以找出当前用户的密钥。如果您的客户端不受信任(即启用 JavaScript 的浏览器),这也会有点问题。不过适用于机器对机器的通信。
备选
您可能需要查看名为 Using JSON Web Tokens as API Keys 的文章。 JSON Web Tokens 提供无状态解决方案。它们也是防篡改的,因为令牌是用 HMAC 签名/散列的。
我正在寻找一种合适的身份验证方法,以便在编写用于我们内部系统的简单 API 时使用。 Stack Overflow 上的其他问题建议使用 HMAC 以及教程链接,我继续并决定实施这些链接。
设置之后,我意识到我不确定这对于实际身份验证有多重要。使用的教程 Here 在客户端列出了一个 public 散列,它从未在服务器端代码中使用过。它只是将 content 和 privateHash 值散列在一起,并在服务器上进行比较。由于这一切都通过 headers 传递,我想知道这实际上有多安全? public哈希值是多少,因为它似乎甚至没有被使用过?
客户:
<?php
$publicHash = '3441df0babc2a2dda551d7cd39fb235bc4e09cd1e4556bf261bb49188f548348';
$privateHash = 'e249c439ed7697df2a4b045d97d4b9b7e1854c3ff8dd668c779013653913572e';
$content = json_encode( array( 'test' => 'content' ) );
$hash = hash_hmac('sha256', $content, $privateHash);
$headers = array(
'X-Public: '.$publicHash,
'X-Hash: '.$hash
);
$ch = curl_init('http://domain.com/api2/core/device/auth');
curl_setopt($ch,CURLOPT_HTTPHEADER,$headers);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
curl_setopt($ch,CURLOPT_POSTFIELDS,$content);
$result = curl_exec($ch);
curl_close($ch);
echo "RESULT\n======\n".print_r($result, true)."\n\n";
?>
服务器
function auth()
{
$app = \Slim\Slim::getInstance();
$request = $app->request();
$publicHash = $request->headers('X-Public');
$contentHash = $request->headers('X-Hash');
$privateHash = 'e249c439ed7697df2a4b045d97d4b9b7e1854c3ff8dd668c779013653913572e';
$content = $request->getBody();
$hash = hash_hmac('sha256', $content, $privateHash);
if ($hash == $combinedHash)
{
$data = array('status' => "success");
response($data);
}
else
{
$data = array('status' => "failed");
response($data);
}
}
我认为您发布的文章以令人困惑的方式使用了术语 hash
。在文章中,$publicHash
是用户名,$privateHash
是用于对有效载荷进行签名的密钥。
换句话说,如文章所说,X-Public
header 的值应该用于从数据库中查询用户特定的密钥。然后使用此密钥从有效负载创建哈希。然后将此哈希值与 X-Hash
header.
如果值匹配,那么您可以确定有效负载未被篡改and/or有效负载的发送者知道密钥。
这种方法不是无状态的。它要求您为每个请求访问数据库以找出当前用户的密钥。如果您的客户端不受信任(即启用 JavaScript 的浏览器),这也会有点问题。不过适用于机器对机器的通信。
备选
您可能需要查看名为 Using JSON Web Tokens as API Keys 的文章。 JSON Web Tokens 提供无状态解决方案。它们也是防篡改的,因为令牌是用 HMAC 签名/散列的。