问题描述
我正在尝试创建授权签名以访问 IAM 安全 API 网关端点.
I am trying to create Authorized Signature to access IAM secured API gateway endpoint.
$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": "我们计算的请求签名与您提供的签名.检查您的 AWS 秘密访问密钥和签名方法.有关详细信息,请参阅服务文档.\n\n此请求的规范字符串应具有一直\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\nString-to-Sign 应该有一直\n'AWS4-HMAC-SHA256\n20161002T231640Z\n20161002/ap-northeast-1/execute-api/aws4_request\n0b8c12e0a5f21137c5739a9d260561dfb6330260561dfb6302fb1dc0dc1dc1db1dc0dc1dc0dc1dc7dc0ac1dc1dc1dbc1dc7
我的字符串签名字符串是
My String-to-sign string is
"AWS4-HMAC-SHA256
20161002T231640Z
20161002/ap-northeast-1/execute-api/aws4_request
fb4f7ebdcb405bceed598ecc097267b929eeb3f8f075b1b7a776f53c8c8c6168"
这与 AWS 在签名中所期望的完全不同.
which is totally different from what AWS expected in signature.
推荐答案
这里是解决方案
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;
}
这篇关于签名版本 4 签名过程在 PHP 中访问 API 网关端点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!