[英]PHP - Delete object from AWS S3 with REST API
我正在嘗試使用 REST API 從亞馬遜 s3 中刪除 object。我創建了一個 curl 命令,但出現 403 錯誤:“SignatureDoesNotMatchThe request signature we calculated does not match the signature you provided”。
我在 AWS 文檔中使用: https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectDELETE.html https://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-header基於-auth.html
這是我的代碼:
$host = 's3.amazonaws.com';
$url = "https://" . $bucket . '.' . $host . '/' . $file;
$date_full = date('D, d M Y H:i:s \G\M\T');
$date = date('Ymd');
$longDate = gmdate('Ymd\THis\Z');
$shortDate = gmdate('Ymd');
$credential = $accessKeyId . '/' . $shortDate . '/' . $region . '/s3/aws4_request';
$hashed_payload = strtolower(hash("sha256", ""));
$headers = [
'X-Amz-Algorithm' => 'AWS4-HMAC-SHA256',
'X-Amz-Credential' => $credential,
'X-Amz-Date' => $longDate,
'X-Amz-Expires' => 86400,
'X-Amz-SignedHeaders' => 'host',
'x-amz-content-sha256' => $hashed_payload,
'Host' => $bucket . '.' . $host,
];
ksort($headers);
$signed_headers_string = strtolower(implode(';', array_keys($headers)));
// Build canonical request
$canonical_request = "DELETE\n"; // HTTPRequestMethod
$canonical_request .= '/' . urlencode("http://s3.amazonaws.com/" . $bucket . "/" . $file) . "\n"; // CanonicalURI
$canonical_request .= "\n"; // CanonicalQueryString
foreach ($headers as $header => $value) {
$canonical_request .= strtolower($header) . ':' . trim($value) . "\n"; //CanonicalHeaders
}
$canonical_request .= $signed_headers_string . "\n"; // SignedHeaders
$canonical_request .= $hashed_payload; // HashedPayload
// Build string to sign
$string_to_sign = "AWS4-HMAC-SHA256\n";
$string_to_sign .= $date_full . "\n";
$string_to_sign .= $date . '/' . $region. "/s3/aws4_request\n";
$string_to_sign .= hash('sha256', $canonical_request);
// Calculate signature
$signature_date = hash_hmac('sha256', $date, 'AWS4' . $secretKey, true);
$signature_region = hash_hmac('sha256', $region, $signature_date, true);
$signature_service = hash_hmac('sha256', 's3', $signature_region, true);
$signature_request = hash_hmac('sha256', 'aws4_request', $signature_service, true);
// Build Signature
$signature = hash_hmac('sha256', $string_to_sign, $signature_request);
// Calculate final Authorization header
$headers['Authorization'] = 'AWS4-HMAC-SHA256 Credential=' . $credential . ', ';
$headers['Authorization'] .= 'SignedHeaders=' . $signed_headers_string . ', ';
$headers['Authorization'] .= 'Signature=' . $signature;
// Convert headers to key:value strings
$curl_headers = array();
foreach ($headers as $header => $value) {
$curl_headers[] = "{$header}:{$value}";
}
// Init curl
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_VERBOSE, 1);
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'PUT');
curl_setopt($curl, CURLINFO_HEADER_OUT, true);
curl_setopt($curl, CURLOPT_HEADER, true);
curl_setopt($curl, CURLOPT_HTTPHEADER, $curl_headers);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "DELETE");
$result = curl_exec($curl);
有人可以幫助我了解問題所在嗎?
您正在對具有大寫和小寫字母的鍵進行排序。 在調用ksort()
之前,在鍵中使用所有小寫字母。
您還包括不需要包含的標頭。 您提到的文檔只要求提供x-amz-date
、 x-amz-content-sha256
和host
。 僅使用那些標頭。
$headers = [
'x-amz-date' => $longDate,
'x-amz-content-sha256' => $hashed_payload,
'host' => $bucket . '.' . $host,
];
ksort($headers);
添加標頭后,您的規范請求應該有一個額外的換行符:
foreach ($headers as $header => $value) {
$canonical_request .= strtolower($header) . ':' . trim($value) . "\n"; //CanonicalHeaders
}
$canonical_request .= "\n";
我不確定是否需要進行此更改,但在 $string_to_sign 中,我使用 $longDate 提供的日期格式,而不是 $date_full:
// Build string to sign
$string_to_sign = "AWS4-HMAC-SHA256\n";
$string_to_sign .= $longDate . "\n";
$string_to_sign .= $date . '/' . $region. "/s3/aws4_request\n";
$string_to_sign .= hash('sha256', $canonical_request);
您正在設置CURLOPT_CUSTOMREQUEST
兩次,首先是PUT
,然后是DELETE
。 最后一個設置可能是正在使用的設置,但我會刪除curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'PUT');
為清楚起見。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.