首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >aws javascript sdk v3 -签名不匹配错误

aws javascript sdk v3 -签名不匹配错误
EN

Stack Overflow用户
提问于 2022-04-07 11:41:26
回答 2查看 568关注 0票数 2

我可以按照步骤如本节所述生成预先签名的url,所以我想测试上传特定的图像marble.jpg,并尝试使用postman测试上传。因此,我复制了预先签名的url并使用一个endpoint请求访问了PUT,并得到了以下错误:

代码语言:javascript
运行
复制
<?xml version="1.0" encoding="UTF-8"?>
<Error>
    <Code>SignatureDoesNotMatch</Code>
    <Message>The request signature we calculated does not match the signature you provided. Check your key and signing method.</Message>
    <Key>records/marble_cave.jpg</Key>
    <BucketName>bucket</BucketName>
    <Resource>/bucket/records/marble.jpg</Resource>
    <RequestId>17E3999B521ABB65</RequestId>
    <HostId>50abb07a-2ad0-4948-96e0-23403f661cba</HostId>
</Error>

设置了以下资源:

  • 我正在使用min.io服务器进行本地测试。
  • 我正在为aws使用nodejs的aws-sdk版本3
  • 我已经三次检查了我的凭证,简单的没有特殊字符的minio creds,我肯定是在提出一个PUT请求。

因此,问题是:

  • 如何使用新的javascript aws版本3设置signatureVersion ( getSignedUrl用于在sdk的v3,import { getSignedUrl } from '@aws-sdk/s3-request-presigner';中生成预先签名的url )
  • 会有什么原因导致这一错误的发生?

用于预先签名的url生成的代码是:

代码语言:javascript
运行
复制
import { getSignedUrl } from '@aws-sdk/s3-request-presigner';
import { PutObjectCommand, S3Client } from '@aws-sdk/client-s3';
const s3Client = new S3Client({
        region: 'us-east-1',
        credentials: {
        accessKeyId: 'minioadmin',
        secretAccessKey: 'minioadmin',
    },
        endpoint: http://172.21.0.2:9000,
        forcePathStyle: true,
    });
  
const bucketParams = {
        Bucket: 'myBucket',
        Key: `marbles.jpg`,
};  
  
const command = new PutObjectCommand(bucketParams);

const signedUrl = await getSignedUrl(s3Client, command, {
        expiresIn: 10000,
})  
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-04-11 16:04:36

解决方案可能与我的其他问题中相同,因此只需复制答案:

我尝试并更改了端口,当我只使用本地主机进行url生成时,put命令似乎可以工作。

因此,在上文中:

代码语言:javascript
运行
复制
new S3Client({
        region: 'us-east-1',
        credentials: {
        accessKeyId: 'minioadmin',
        secretAccessKey: 'minioadmin',
    },
        endpoint: http://172.21.0.2:9000,
        forcePathStyle: true,
    });  

我用:

代码语言:javascript
运行
复制
new S3Client({
        region: 'us-east-1',
        credentials: {
        accessKeyId: 'minioadmin',
        secretAccessKey: 'minioadmin',
    },
        endpoint: http://172.21.0.2, // or 127.0.0.1
        forcePathStyle: true,
    });  

注意,我没有使用任何端口号,所以默认情况是80

如果您使用的是docker-compose,请添加此配置:

代码语言:javascript
运行
复制
. 
.
.
ports:  
  - 80:9000  

而且效果很好。

票数 1
EN

Stack Overflow用户

发布于 2022-06-30 13:05:55

一年前,我偶然发现了这个问题,新的V3 SDK有一个bug,它在签署URL时没有考虑端口。见这里https://github.com/aws/aws-sdk-js-v3/issues/2726

我所做的工作最终实现了重写代码中的getSignedUrl,并按如下方式添加了缺少的端口:

代码语言:javascript
运行
复制
import {BuildMiddleware, MetadataBearer, RequestPresigningArguments} from '@aws-sdk/types';
import {Client, Command} from '@aws-sdk/smithy-client';
import {HttpRequest} from '@aws-sdk/protocol-http';
import {formatUrl} from '@aws-sdk/util-format-url';
import {S3RequestPresigner} from '@aws-sdk/s3-request-presigner';


export const getSignedUrl = async <
  InputTypesUnion extends object,
  InputType extends InputTypesUnion,
  OutputType extends MetadataBearer = MetadataBearer
  >(
  client: Client<any, InputTypesUnion, MetadataBearer, any>,
  command: Command<InputType, OutputType, any, InputTypesUnion, MetadataBearer>,
  options: RequestPresigningArguments = {}
): Promise<string> => {
  const s3Presigner = new S3RequestPresigner({ ...client.config });
  const presignInterceptMiddleware: BuildMiddleware<InputTypesUnion, MetadataBearer> =
    (next, context) => async (args) => {
      const { request } = args;
      if (!HttpRequest.isInstance(request)) {
        throw new Error('Request to be presigned is not an valid HTTP request.');
      }
      // Retry information headers are not meaningful in presigned URLs
      delete request.headers['amz-sdk-invocation-id'];
      delete request.headers['amz-sdk-request'];
      // User agent header would leak sensitive information
      delete request.headers['x-amz-user-agent'];
      delete request.headers['x-amz-content-sha256'];

      delete request.query['x-id'];

      if (request.port) {
        request.headers['host'] = `${request.hostname}:${request.port}`;
      }

      const presigned = await s3Presigner.presign(request, {
        ...options,
        signingRegion: options.signingRegion ?? context['signing_region'],
        signingService: options.signingService ?? context['signing_service'],
      });
      return {
        // Intercept the middleware stack by returning fake response
        response: {},
        output: {
          $metadata: { httpStatusCode: 200 },
          presigned,
        },
      } as any;
    };
  const middlewareName = 'presignInterceptMiddleware';
  client.middlewareStack.addRelativeTo(presignInterceptMiddleware, {
    name: middlewareName,
    relation: 'before',
    toMiddleware: 'awsAuthMiddleware',
    override: true,
  });

  let presigned: HttpRequest;
  try {
    const output = await client.send(command);
    //@ts-ignore the output is faked, so it's not actually OutputType
    presigned = output.presigned;
  } finally {
    client.middlewareStack.remove(middlewareName);
  }

  return formatUrl(presigned);
};
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71781531

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档