为啥会提示“我们计算的请求签名与您提供的签名不匹配”。对于 GET 但不是 PUT 对于 OpenSearch?

Posted

技术标签:

【中文标题】为啥会提示“我们计算的请求签名与您提供的签名不匹配”。对于 GET 但不是 PUT 对于 OpenSearch?【英文标题】:Why do I get "The request signature we calculated does not match the signature you provided." for GET but not PUT for OpenSearch?为什么会提示“我们计算的请求签名与您提供的签名不匹配”。对于 GET 但不是 PUT 对于 OpenSearch? 【发布时间】:2021-12-20 10:50:55 【问题描述】:

我正在关注 this guide 使用 Node.js(适用于 javascript 的 AWS 开发工具包的第 3 版)签署对 Amazon OpenSearch 服务的 HTTP 请求。

当我复制准确的示例代码并导出我的授权用户的AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEY 时,添加项目的PUT index/type/id 请求成功:

201 Created
Response body: "_index":"products","_type":"_doc","_id":"2","_version":1,"result":"created","_shards":"total":2,"successful":2,"failed":0,"_seq_no":0,"_primary_term":1

但是,当我将请求更改为 GET /_search 端点时,我得到:

403 Forbidden
Response body: "message":"The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details."

用户已完全授权索引:

    
      "Effect": "Allow",
      "Principal": 
        "AWS": "arn:aws:iam::**:user/aws-elasticbeanstalk-ec2-user"
      ,
      "Action": "es:*",
      "Resource": "arn:aws:es:ap-southeast-2:**:domain/mydomain/*"
    ,

如何更正我的签名?

这是我从上面链接修改的代码:

const  HttpRequest  = require('@aws-sdk/protocol-http')
const  defaultProvider  = require('@aws-sdk/credential-provider-node')
const  SignatureV4  = require('@aws-sdk/signature-v4')
const  NodeHttpHandler  = require('@aws-sdk/node-http-handler')
const  Sha256  = require('@aws-crypto/sha256-browser')

const region = ''
const domain = ''
const index = 'products'
const type = '_search'
const createBody = (query) => (
  query: 
    multi_match: 
      query,
      type: 'phrase',
      fields: [
        'tags',
        'name',
        'category',
        'maker'
      ]
    
  ,
  highlight: 
    pre_tags: [''],
    post_tags: [''],
    fields: 
      tags: ,
      name: ,
      category: ,
      maker: 
    
  
)

searchIndex('sh').then(() => process.exit())

async function searchIndex (query) 
  const request = new HttpRequest(
    body: JSON.stringify(createBody(query)),
    headers: 
      'Content-Type': 'application/json',
      host: domain
    ,
    hostname: domain,
    method: 'GET',
    path: index + '/' + type
  )

  const signer = new SignatureV4(
    credentials: defaultProvider(),
    region: region,
    service: 'es',
    sha256: Sha256
  )

  const signedRequest = await signer.sign(request)

  const client = new NodeHttpHandler()
  const  response  = await client.handle(signedRequest)
  console.log(response.statusCode + ' ' + response.body.statusMessage)

  let responseBody = ''
  return new Promise((resolve) => 
    response.body.on('data', (chunk) => 
      responseBody += chunk
    )
    response.body.on('end', () => 
      console.log('Response body: ' + responseBody)
      resolve(responseBody)
    )
  , (error) => 
    console.log('Error: ' + error)
  )

【问题讨论】:

@ErmiyaEskandary 我的 javascript linter 自动更改了这一点 - 对象属性名称上的引号不会影响请求,但感谢您的建议。 在错误块内 - 试试console.log(this.request.httpRequest); console.log(this.httpResponse);,你会得到什么? @ErmiyaEskandary 我添加了, (error) => console.log('here') console.log('Error: ' + error) ),但它从不记录here,它只记录前一个块(response.body.on('end')。我尝试记录您建议的一些变体,但它们都是undefined 【参考方案1】:

我也有这个问题,使用相同的教程

阅读docs on request body searches,我发现它声明如下:

注意 _search API 接受 HTTP GET 和 POST 请求正文 搜索,但并非所有 HTTP 客户端都支持将请求正文添加到 获取请求。 POST 是更通用的选择。

将我的方法更改为 POST 为我解决了问题

【讨论】:

以上是关于为啥会提示“我们计算的请求签名与您提供的签名不匹配”。对于 GET 但不是 PUT 对于 OpenSearch?的主要内容,如果未能解决你的问题,请参考以下文章

AWSSecretsManagerException:我们计算的请求签名与您提供的签名不匹配

我们计算的请求签名与您提供的签名不匹配 - AWS

我们计算的请求签名与您提供的签名不匹配。检查您的 AWS 秘密访问密钥和签名方法

AWS S3 - 我们计算的请求签名与您提供的签名不匹配。检查您的密钥和签名方法

使用 Amazon API MWS 进行签名查询

SignatureDoesNotMatch 错误使用 restTemplate 获取 S3 的 url 请求