只有仍在使用 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 并使用基于 IAM 的身份验证在 Amazon 云中的 Elasticsearch 托管服务的任何人有益。