PHP REST API身份验证

3
我正在为一个PHP应用程序构建RESTful API。目前,API仅接受和响应json。请求、路由和响应均由框架处理,但我需要构建一个自定义身份验证机制。
我想添加两个项目以增强安全性并避免重放攻击:时间戳和nonce。
除了这两个项目之外,我希望进行合理检查,以确保从安全性或可用性角度来看没有漏掉任何其他明显的问题。
实体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);
1个回答

2

hash_hmac()函数需要第二个参数为字符串,而你传入的是解码后的JSON对象。除此之外,你的方法看起来很标准。entity_id也应该由HMAC签名保护,所以我建议将其保留在请求体中,否则你的签名计算会变得更加复杂,而收益却微乎其微。


我将json_encode传递给hash_hmac,而不是json_decode,所以我认为这是可以的。使用这种方法是否意味着API不能有任何GET请求 - 因为始终必须有CURL_POSTFIELDS? - JonoB
你提到的 json_encode 在你发布的代码中并不存在。根据你发布的代码,很明显你的API不支持GET请求,因为你要求在JSON POST主体中包含一个 entity_id 键,而这个键在GET请求中永远不会存在。除非你决定将整个JSON字符串作为单个GET参数传递,否则你需要为GET请求设计一个非常不同的签名算法。 - lanzz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接