我正在尝试创建授权签名以访问 IAM 安全 API 网关端点。
$alg = "SHA256";
$CanonicalRequest = "GET\n/dev/pets\n\nhost:3r4fgts8e5.execute-api.ap-northeast-1.amazonaws.com\nx-amz-date:".$dd."\n\nhost;x-amz-date\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855";
$CR = str_replace("\n", "", $CanonicalRequest);
$CR = str_replace("\r", "", $CR);
$CR = strtolower($CR);
$StringToSign = "AWS4-HMAC-SHA256\n".$dd."\n".$date->format( 'Ymd' )."/ap-northeast-1/execute-api/aws4_request\n".hash( $alg, $CR )."";
// 1) HMACs
$kSecret = 'AWS4' . $secret_key;
$kDate = hash_hmac( $alg, $date->format( 'Ymd' ), $kSecret, true );
$kRegion = hash_hmac( $alg, $region, $kDate, true );
$kService = hash_hmac( $alg, $service, $kRegion, true );
$kSigning = hash_hmac( $alg, 'aws4_request', $kService, true );
$signature = hash_hmac( $alg, $StringToSign, $kSigning );
$authorization = array(
'Credential=' . $access_key . '/' . implode( '/', $scope ),
'SignedHeaders=' . implode( ';', array_keys( $can_headers ) ),
'Signature=' . $signature,
);
$authorization = $request['algorithm'] . ' ' . implode( ',', $authorization );
$request['Authorization'] = $authorization;
但我收到“我们计算的请求签名与您提供的签名不匹配”错误
"message": "The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details.\n\nThe Canonical String for this request should have been\n'GET\n/dev/pets\n\nhost:3r4fgts8e5.execute-api.ap-northeast-1.amazonaws.com\nx-amz-date:20161002T231640Z\n\nhost;x-amz-date\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855'\n\nThe String-to-Sign should have been\n'AWS4-HMAC-SHA256\n20161002T231640Z\n20161002/ap-northeast-1/execute-api/aws4_request\n0b8c12e0a5f21137c5739a9d26056dfb081218631a9adcf37db1d2e09a014c4e'\n"
我的字符串到签名字符串是
"AWS4-HMAC-SHA256
20161002T231640Z
20161002/ap-northeast-1/execute-api/aws4_request
fb4f7ebdcb405bceed598ecc097267b929eeb3f8f075b1b7a776f53c8c8c6168"
这与 AWS 在签名中所期望的完全不同。
最佳答案
这是解决方案
private function signRequest(){
$method ='GET';
$uri = '/dev';
$json = file_get_contents('php://input');
$obj = json_decode($json);
if(isset($obj->method))
{
$m = explode("|", $obj->method);
$method = $m[0];
$uri .= $m[1];
}
$secretKey = $this->session->data['aws_secret'];
$access_key = $this->session->data['aws_key'];
$token = $this->session->data['aws_token'];
$region = 'ap-southeast-1';
$service = 'execute-api';
$options = array(); $headers = array();
$host = "YOUR-API-HOST.execute-api.ap-southeast-1.amazonaws.com";
//Or you can define your host here.. I am using API gateway.
$alg = 'sha256';
$date = new DateTime( 'UTC' );
$dd = $date->format( 'Ymd\THis\Z' );
$amzdate2 = new DateTime( 'UTC' );
$amzdate2 = $amzdate2->format( 'Ymd' );
$amzdate = $dd;
$algorithm = 'AWS4-HMAC-SHA256';
$parameters = (array) $obj->data;
if($obj->data == null || empty($obj->data))
{
$obj->data = "";
}else{
$param = json_encode($obj->data);
if($param == "{}")
{
$param = "";
}
$requestPayload = strtolower($param);
$hashedPayload = hash($alg, $requestPayload);
$canonical_uri = $uri;
$canonical_querystring = '';
$canonical_headers = "content-type:"."application/json"."\n"."host:".$host."\n"."x-amz-date:".$amzdate."\n"."x-amz-security-token:".$token."\n";
$signed_headers = 'content-type;host;x-amz-date;x-amz-security-token';
$canonical_request = "".$method."\n".$canonical_uri."\n".$canonical_querystring."\n".$canonical_headers."\n".$signed_headers."\n".$hashedPayload;
$credential_scope = $amzdate2 . '/' . $region . '/' . $service . '/' . 'aws4_request';
$string_to_sign = "".$algorithm."\n".$amzdate ."\n".$credential_scope."\n".hash('sha256', $canonical_request)."";
//string_to_sign is the answer..hash('sha256', $canonical_request)//
$kSecret = 'AWS4' . $secretKey;
$kDate = hash_hmac( $alg, $amzdate2, $kSecret, true );
$kRegion = hash_hmac( $alg, $region, $kDate, true );
$kService = hash_hmac( $alg, $service, $kRegion, true );
$kSigning = hash_hmac( $alg, 'aws4_request', $kService, true );
$signature = hash_hmac( $alg, $string_to_sign, $kSigning );
$authorization_header = $algorithm . ' ' . 'Credential=' . $access_key . '/' . $credential_scope . ', ' . 'SignedHeaders=' . $signed_headers . ', ' . 'Signature=' . $signature;
$headers = [
'content-type'=>'application/json',
'x-amz-security-token'=>$token,
'x-amz-date'=>$amzdate,
'Authorization'=>$authorization_header];
return $headers;
}
关于php - 签名版本 4 签名过程在 PHP 中访问 API 网关端点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39822768/