Cha*_*ieT 4 php curl signing amazon-web-services
我正在尝试签署 AWS API 请求,然后使用 cURL。
目的是将跟踪号码提交给服务提供商的 API,并使用响应。
我对 AWS API 完全是个菜鸟,经过多次测试后找不到我的错误。
我尝试了很多方法,但都导致了{"message":"Forbidden"}。
这是我当前的脚本:
<?php
$accessKeyId = "AKIA55D**********";
$secretAccessKey = "NQ0xcl**********";
$method ='GET';
$uri = '/tracking/shipments';
$secretKey = $secretAccessKey;
$access_key = $accessKeyId;
$region = 'af-south-1';
$service = 'execute-api';
$host = "https://api.shiplogic.com";
$alg = 'sha256';
$date = new DateTime('Africa/Johannesburg');
$dd = $date->format( 'Ymd\THis\Z' );
$amzdate2 = new DateTime( 'Africa/Johannesburg' );
$amzdate2 = $amzdate2->format( 'Ymd' );
$amzdate = $dd;
$algorithm = 'AWS4-HMAC-SHA256';
$canonical_uri = $uri;
$canonical_querystring = '';
$canonical_headers = "host:".$host."\n"."x-amz-date:".$amzdate."\n";
$signed_headers = 'host;x-amz-date';
$canonical_request = "".$method."\n".$canonical_uri."\n".$canonical_querystring."\n".$canonical_headers."\n".$signed_headers;
$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-date'=>$amzdate,
'Authorization'=>$authorization_header];
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => 'https://api.shiplogic.com/tracking/shipments?tracking_reference=M3RPH',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => array(
'X-Amz-Date: '.$amzdate.'',
'Authorization: ' . $authorization_header . ''
),
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;
Run Code Online (Sandbox Code Playgroud)
我收到的回复是{"message":"Forbidden"}
我究竟做错了什么?
按照评论中已经指出的方式安装Amazon 的 PHP SDK 。
composer require aws/aws-sdk-php
Run Code Online (Sandbox Code Playgroud)
您尝试调用的 API 的文档有1 个 PHP 代码示例,并且它使用该 SDK。您所需要做的就是插入您的凭据。
use Aws\Credentials\Credentials;
use Aws\Signature\SignatureV4;
use Psr\Http\Message\RequestInterface;
function sign(
RequestInterface $request,
string $accessKeyId,
string $secretAccessKey
): RequestInterface {
$signature = new SignatureV4('execute-api', 'af-south-1');
$credentials = new Credentials($accessKeyId, $secretAccessKey);
return $signature->signRequest($request, $credentials);
}
Run Code Online (Sandbox Code Playgroud)
可以看到输入$request和返回值都是相同的RequestInterface 类型。因此,它为您提供了一个带有正确签名的修改后的请求对象(如果您的密钥和参数有效)。
如果您正在使用curl,您可能还没有此请求对象。Amazon 的 API 使用PSR-7 标准请求接口,大多数框架如果有请求对象就会实现此接口。
如果您手头没有请求对象,您可以使用Guzzle 的实现。所需的包已作为Amazon SDK 的依赖项安装。您可以从 Github 永久链接安装这两个突出显示的软件包。
$request = new GuzzleHttp\Psr7\Request(
'GET',
'https://api.shiplogic.com/tracking/shipments',
[
// Maybe you still need headers.
]
);
$signed_request = sign($request);
$client = new \GuzzleHttp\Client();
$response = $client->send($signed_request);
Run Code Online (Sandbox Code Playgroud)
正如评论中提到的,应尽可能避免创建自己的安全组件实现。重写代码以使用此请求对象要容易得多,尤其是对于将来的维护而言。
另请记住,您的凭据可能只是无效,或者无法访问您所请求的资源。乍一看,您的大部分实现似乎都遵循签名协议的预期(尽管您只需要一个小错误,它就不会工作),所以如果您确定检查了所有内容,那么它可能就这么简单。
| 归档时间: |
|
| 查看次数: |
1905 次 |
| 最近记录: |