2017-10-22 261 views
1

我試圖生成預簽名的URL,然後通過瀏覽器將文件上傳到S3。我的服務器端代碼如下所示,並生成以下URL:使用簽名URL上傳到S3時獲取403(禁止)

let s3 = new aws.S3({ 
    // for dev purposes 
    accessKeyId: 'MY-ACCESS-KEY-ID', 
    secretAccessKey: 'MY-SECRET-ACCESS-KEY' 
}); 
let params = { 
    Bucket: 'reqlist-user-storage', 
    Key: req.body.fileName, 
    Expires: 60, 
    ContentType: req.body.fileType, 
    ACL: 'public-read' 
}; 
s3.getSignedUrl('putObject', params, (err, url) => { 
    if (err) return console.log(err); 
    res.json({ url: url }); 
}); 

這部分似乎正常工作。如果我登錄它並將它傳遞到前端,我可以看到該URL。然後在前端,我試圖用axios和簽名的URL上傳文件:

.then(res => { 
    var options = { headers: { 'Content-Type': fileType } }; 
    return axios.put(res.data.url, fileFromFileInput, options); 
    }).then(res => { 
    console.log(res); 
    }).catch(err => { 
    console.log(err); 
    }); 
} 

這樣,我得到了403 Forbidden錯誤。如果我按照鏈接,有一些XML更多信息:

<Error> 
<Code>SignatureDoesNotMatch</Code> 
<Message> 
The request signature we calculated does not match the signature you provided. Check your key and signing method. 
</Message> 
...etc 

回答

1

您的請求需要與簽名完全匹配。一個顯而易見的問題是,即使您將它包含在簽名中,實際上您並沒有在請求中包含預設的ACL。更改爲:

var options = { headers: { 'Content-Type': fileType, 'x-amz-acl': 'public-read' } }; 
+0

謝謝,這不是,但我覺得我對問題的感覺更好。我很確定有些東西不匹配,我只是沒有弄清楚究竟是什麼。 – Alan

+1

雖然這應該是其中的一部分。這是一個非常確定性的過程,對不一致的容忍度爲零。根據您實際發送的請求,錯誤消息中的CanonicalRequest將間接地告訴您應該將哪些參數傳遞給getSignedUrl()。 –

+0

謝謝,終於找到了正確的標題,並取得了成功的放入請求。 – Alan

1

1)您可能需要使用S3V4簽名取決於如何將數據傳輸到AWS(對塊流)。創建客戶端如下:

var s3 = new AWS.S3({ 
    signatureVersion: 'v4' 
}); 

2)不要添加新標頭或修改現有標頭。該請求必須完全符合簽名。

3)確保生成的url與發送給AWS的內容匹配。

4)做一個測試請求,在簽名前刪除這兩行(並從你的PUT中刪除頭文件)。這將有助於縮小您的問題:

ContentType: req.body.fileType, 
    ACL: 'public-read' 
+0

謝謝,我跑過這個列表,我相信也許有一個標題不匹配。如何比較簽名url中的標題和我發送的標題? – Alan

+0

你在調用getSignedUrl時在你的params中指定HTTP頭。還要注意Michael sqlbot的回覆x-amz-acl頭。邁克爾的參數是正確的。確保你在你的PUT中包含相同的頭文件。 –

+0

一個額外的項目。在簽名和調用放入時,使用文件大小添加Content-Length。我沒有看到指定的區域。創建客戶端時添加此項。 –

1

有同樣的問題,這裏是你需要如何去解決它,

  1. 提取標識的URL的文件名部分。 執行打印,您正在使用查詢字符串參數正確提取您的文件名部分。這很關鍵。
  2. 使用查詢字符串參數編碼到URI的文件名編碼。
  3. 從編碼文件名連同其他路徑或從您的節點服務中返回您的lambda網址。

現在從axios與該網址發佈,它將工作。

EDIT1: 如果您傳遞錯誤的內容類型,您的簽名也將無效。

請確保您創建預簽名url的內容類型與您正在使用它的內容類型相同。

希望它有幫助。

+0

謝謝,我給了這個嘗試,但我不認爲這是問題。該URL已經被正確編碼了,如果我試圖「重新編碼」它,它實際上變成了一個死鏈接。 – Alan

+0

您能否確認您的內容類型與axios相同,然後創建了signedurl? – Kannaiyan