本文介绍了签名版本 4 签名过程在 PHP 中访问 API 网关端点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试创建授权签名以访问 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 网关端点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-03 10:59