我正在尝试创建授权签名以访问IAM安全API网关端点。
$alg = "SHA256";
$CanonicalRequest = "GETn/dev/petsnnhost:3r4fgts8e5.execute-api.ap-northeast-1.amazonaws.comnx-amz-date:".$dd."nnhost;x-amz-datene3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855";
$CR = str_replace("n", "", $CanonicalRequest);
$CR = str_replace("r", "", $CR);
$CR = strtolower($CR);
$StringToSign = "AWS4-HMAC-SHA256n".$dd."n".$date->format( 'Ymd' )."/ap-northeast-1/execute-api/aws4_requestn".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": "我们计算的请求签名与您提供的签名。检查您的AWS秘密访问密钥和签名方法。详细信息请参考服务文档此请求的规范字符串应该具有被'GET n n n /dev/宠物nhost: 3 r4fgts8e5.execute api.ap -东北- 1. amazonaws.com nx-amz-date: 20161002 t231640z n nhost; x-amz-date n nThe ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"字符串到签名应该有被 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"
解决方案
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( 'YmdTHisZ' );
$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;
}