GetPreSignedUrlRequest - SignatureDoesNotMatch

时间:2015-12-07 21:02:31

标签: amazon-s3

我正在尝试上传测试PDF文件并使用GetPreSignedUrlRequest生成预先签名的网址,但在尝试访问预先签名的网址时出现以下错误:

<Error>
    <Code>SignatureDoesNotMatch</Code>
    <Message>The request signature we calculated does not match the signature you provided. Check your key and signing method.</Message>
    <AWSAccessKeyId>xxxxxxxxxxxxxxxxxxxxxxx</AWSAccessKeyId>
    <StringToSign>GET 1607367406 /TESTBUCKET/TEST.pdf</StringToSign>
    <SignatureProvided>qMFjJ+j0wDtXKUjWW3jGQSktEMA=</SignatureProvided>
    <StringToSignBytes> 47 45 54 0a 0a 0a 31 36 30 37 33 36 37 34 30 36 0a 2f 65 61 64 63 74 64 62 75 63 6b 65 74 72 65 70 6f 72 74 2f 63 72 6f 73 73 70 61 74 69 65 6e 74 2e 70 64 66</StringToSignBytes>
    <RequestId>9FE8E72C7C436320</RequestId>
    <HostId>4z49ibT2YqJxGz436pEtuSnV4L2chzy+vmsKtAbGZBJS+We39yquFwYS+5Wd98sdtrsnBBb9YHg=</HostId>
</Error>

我的代码:

public HttpWebResponse UploadObject(string filePath, string url)
{
    HttpWebRequest httpRequest = WebRequest.Create(url) as HttpWebRequest;
    httpRequest.Method = "PUT";
    using (Stream dataStream = httpRequest.GetRequestStream())
    {
        using (FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
        {
            byte[] buffer = new byte[fileStream.Length];
            int bytesRead = 0;
            while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) > 0)
            {
                dataStream.Write(buffer, 0, bytesRead);
            }
        }
    }
    return httpRequest.GetResponse() as HttpWebResponse;
}

public string GeneratePreSignedURL(string key)
{
    GetPreSignedUrlRequest request = new GetPreSignedUrlRequest
    {
        BucketName = _bucket,
        Key = key,
        Verb = HttpVerb.PUT,
        Expires = DateTime.Now.AddYears(5)
    };
    return client.GetPreSignedURL(request);
}

消费者:

public void UploadValidPdfObject()
{
    string applicationName = ConfigurationManager.AppSettings["ApplicationName"];
    string s3ReportBucket = ConfigurationManager.AppSettings["S3ReportBucketName"];
    byte[] result = File.ReadAllBytes(@"c:\test.pdf");
    string fileKey =  DateTime.UtcNow.Ticks.ToString();
    string fileName = fileKey + ".pdf";
    string fileNameResult = fileKey + "1.pdf";
    string filePath = GetCurrentExeLoccation() + fileName;
    //SET CloudStoreType.AmazonS3Direct, s3ReportBucket, applicationName
    string preSignedURL = GeneratePreSignedURL(fileKey + ".pdf");
    File.WriteAllBytes(filePath, result);
    UploadObject(filePath, preSignedURL);
    if (preSignedURL != null)
    {
        string resultFilePath = GetCurrentExeLoccation() + fileNameResult;
        WebClient webClient = new WebClient();
        webClient.DownloadFile(preSignedURL, GetCurrentExeLoccation() + resultFilePath);
        Assert.IsTrue(File.Exists(resultFilePath));
        File.Delete(filePath);
        File.Delete(resultFilePath);
    }           
}

1 个答案:

答案 0 :(得分:1)

错误响应表示您正在尝试GET某个对象...但GeneratePreSignedURL()中的代码似乎会为PUT请求生成预先签名的网址。上传和下载相同的文件需要为每个操作使用不同的签名,因为http动词是要签名的字符串的一部分,因此在动词更改时更改签名,即使没有其他操作也是如此。