此調整僅適用於仍在使用Amazon SDK PHP版本2的用戶。在版本3中,它默認支持。
對於已簽名的請求,我通過添加用於簽署請求的中間件來更新當前的elsticsearch客戶端處理程序。
$elasticConfig = Configure::read('ElasticSearch');
$middleware = new AwsSignatureMiddleware();
$defaultHandler = \Elasticsearch\ClientBuilder::defaultHandler();
$awsHandler = $middleware($defaultHandler);
$clientBuilder = \Elasticsearch\ClientBuilder::create();
$clientBuilder->setHandler($awsHandler)
->setHosts([$elasticConfig['host'].':'.$elasticConfig['port']]);
$client = $clientBuilder->build();
我用下面的庫用於此目的
use Aws\Common\Credentials\CredentialsInterface;
use Aws\Common\Signature\SignatureInterface;
use Guzzle\Http\Message\Request;
class AwsSignatureMiddleware
{
/**
* @var \Aws\Credentials\CredentialsInterface
*/
protected $credentials;
/**
* @var \Aws\Signature\SignatureInterface
*/
protected $signature;
/**
* @param CredentialsInterface $credentials
* @param SignatureInterface $signature
*/
public function __construct()
{
$amazonConf = Configure::read('AmazonSDK');
$this->credentials = new \Aws\Common\Credentials\Credentials($amazonConf['key'], $amazonConf['secret']);
$this->signature = new \Aws\Common\Signature\SignatureV4('es', 'eu-west-1');
}
/**
* @param $handler
* @return callable
*/
public function __invoke($handler)
{
return function ($request) use ($handler) {
$headers = $request['headers'];
if ($headers['host']) {
if (is_array($headers['host'])) {
$headers['host'] = array_map([$this, 'removePort'], $headers['host']);
} else {
$headers['host'] = $this->removePort($headers['host']);
}
}
if (!empty($request['body'])) {
$headers['x-amz-content-sha256'] = hash('sha256', $request['body']);
}
$psrRequest = new Request($request['http_method'], $request['uri'], $headers);
$this->signature->signRequest($psrRequest, $this->credentials);
$headerObj = $psrRequest->getHeaders();
$allHeaders = $headerObj->getAll();
$signedHeaders = array();
foreach ($allHeaders as $header => $allHeader) {
$signedHeaders[$header] = $allHeader->toArray();
}
$request['headers'] = array_merge($signedHeaders, $request['headers']);
return $handler($request);
};
}
protected function removePort($host)
{
return parse_url($host)['host'];
}
}
確切線我調整用於該目的是
if (!empty($request['body'])) {
$headers['x-amz-content-sha256'] = hash('sha256', $request['body']);
}
對於PUT和POST請求的有效載荷的哈希是錯誤的,因爲我在生成有效載荷時沒有考慮請求主體。
希望此代碼對任何使用Amazon SDK PHP版本2並在Amazon雲中使用基於IAM的Elasticsearch託管服務身份驗證的用戶都有益。
http://docs.aws.amazon.com/general/latest/gr/signature-v4-troubleshooting.html –
是@VladHolubiev我嘗試了與他們記錄的相同方式,並且它對GET操作起作用,例如(search,find物品等)。但不適用於PUT操作。 – vims
如果它適用於一種而非另一種,那麼請求中的細微差異會使邏輯無效。該錯誤消息爲您提供了一些有價值的麻煩搜索信息,包括規範請求(以sha256hex有效負載哈希結束)和字符到符號(以標準請求的sha256hex哈希結束)。找到簽名過程中產生錯誤結果的步驟,並解決在該步驟發生的問題。它只能在那裏,而不是在以後,因爲在任何步驟的錯誤結果總是會級聯。 –