【问题标题】:PHP rest API authenticationPHP REST API 认证
【发布时间】:2012-09-11 21:15:56
【问题描述】:

我正在为 php 应用程序构建一个宁静的 API。目前,API 将只接受和响应 json。请求、路由和响应都由框架处理,但我需要构建一个自定义的身份验证机制。

为了额外的安全性和避免重放攻击,我想添加两项:时间戳和随机数。

  1. 除了这两项之外,我还需要进行健全性检查,以确保从安全性或可用性的角度来看,我没有遗漏任何其他非常明显的内容。
  2. entity_id 应该放在标头而不是请求中吗?

到目前为止,这是我用于身份验证的内容:

function authenticate_request()
{
    $request = json_decode(file_get_contents('php://input'));
    $request_headers = apache_request_headers();

    if ( ! isset($request_headers['X-Auth']) OR ! isset($request_headers['X-Auth-Hash'])) {
        return false;
    }

    $user = User::get_by('public_key', $request_headers['X-Auth']);

    if ( ! $user) {
        return false;
    }

    // every request must contain a valid entity
    if (isset($request->entity_id) && $request->entity_id > 0) {
        $this->entity_id = $request->entity_id;
    } else {
        return false;
    }

    $entity = Entity::find($this->entity_id);
    if ( ! $entity) {
        return false;
    }

    // validate the hash
    $hash = hash_hmac('sha256', $request, $user->private_key);

    if ($hash !== $request_headers['X-Auth-Hash']) {
        return false;
    }

    return true;
}

curl 请求示例:

$public_key = '123';
$private_key = 'abc';

$data = json_encode(array('entity_id' => '3087', 'date_end' => '2012-05-28'));
$hash = hash_hmac('sha256', $data, $private_key);
$headers = array(
    'X-Auth: '. $public_key,
    'X-Auth-Hash: '. $hash
);
$ch = curl_init('http://localhost/myapp/api/reports/');

curl_setopt($ch,CURLOPT_HTTPHEADER,$headers);
curl_setopt($ch,CURLOPT_POSTFIELDS, $data);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);

$result = curl_exec($ch);
curl_close($ch);

print_r($result);

【问题讨论】:

    标签: php api rest authentication


    【解决方案1】:

    hash_hmac() 期望它的第二个参数是一个字符串,你传递的是 decoded JSON 对象。除此之外,您的方法似乎很标准。 entity_id 也应该受到 HMAC 签名的保护,所以我会将其保留在请求正文中,否则您的签名计算会变得更加复杂而没有实际收益。

    【讨论】:

    • 我将 json_encode 传递给 hash_hmac,而不是 json_decode,所以我认为没关系。使用这种方法是否意味着不能有任何对 API 的 GET 请求 - 因为总是必须有 CURL_POSTFIELDS?
    • 您提到的json_encode 不在您发布的代码中。使用您发布的代码,很明显您不能向您的 API 发送 GET 请求,因为您需要在 JSON POST 正文中使用 entity_id 键,而该键永远不会出现在 GET 请求中。除非您决定将整个 JSON 字符串作为单个 GET 参数传递,否则您将需要对 GET 请求使用非常不同的签名算法。
    猜你喜欢
    • 1970-01-01
    • 2014-05-31
    • 2013-02-25
    • 2013-09-28
    • 2017-05-31
    • 2014-05-04
    • 2015-10-18
    • 2016-06-13
    • 1970-01-01
    相关资源
    最近更新 更多