2012-01-24 72 views
5

我試圖通過分段上傳將文件上載到Amazon Java SDK。這個想法是將一個upload-id傳遞給一個小程序,該小程序將文件部分放入只讀桶中。以這種方式,我避免將AWS憑證存儲在小程序中。使用分段上傳將文件放入Amazon S3

在我的測試中,我用boto(python)生成一個upload-id並將一個文件存儲到存儲桶中。這很好。

我的Applet從S3獲取「403 Access denied」,我不知道爲什麼。

這裏是我的代碼(這部分從http://docs.amazonwebservices.com/AmazonS3/latest/dev/llJavaUploadFile.html拍攝):

AmazonS3 s3Client = new AmazonS3Client(); 
List<PartETag> partETags = new ArrayList<PartETag>(); 

long contentLength = file.length(); 
long partSize = Config.getInstance().getInt("part_size"); 
String bucketName = Config.getInstance().getString("bucket"); 
String keyName = "mykey"; 
String uploadId = getParameter("upload_id"); 

try { 
    long filePosition = 0; 
    for (int i = 1; filePosition < contentLength; i++) { 

     partSize = Math.min(partSize, (contentLength - filePosition)); 

     // Create request to upload a part. 
     UploadPartRequest uploadRequest = new UploadPartRequest() 
      .withBucketName(bucket).withKey(keyName) 
      .withUploadId(uploadId).withPartNumber(i) 
      .withFileOffset(filePosition) 
      .withFile(file) 
      .withPartSize(partSize); 

     // Upload part and add response to our list. 
     partETags.add(s3Client.uploadPart(uploadRequest).getPartETag()); 

     filePosition += partSize; 
    } 

    System.out.println("Completing upload"); 
    CompleteMultipartUploadRequest compRequest = new 
       CompleteMultipartUploadRequest(bucket, 
              keyName, 
              uploadId, 
              partETags); 

    s3Client.completeMultipartUpload(compRequest); 
} catch (Exception e) { 
    s3Client.abortMultipartUpload(new AbortMultipartUploadRequest(
      bucketName, keyName, uploadId)); 
} 

在小程序調試日誌,我發現這一點,那麼:

INFO: Sending Request: PUT https://mybucket.s3.amazonaws.com /mykey Parameters: (uploadId: V4hwobOLQ1rYof54zRW0pfk2EfhN7B0fpMJTOpHOcmaUl8k_ejSo_znPI540.lpO.ZO.bGjh.3cx8a12ZMODfA--, partNumber: 1,) Headers: (Content-Length: 4288546, Content-Type: application/x-www-form-urlencoded; charset=utf-8,) 
24.01.2012 16:48:42 com.amazonaws.http.AmazonHttpClient handleErrorResponse 
INFO: Received error response: Status Code: 403, AWS Service: null, AWS Request ID: DECF32CCFEE9EBF0, AWS Error Code: AccessDenied, AWS Error Message: Access Denied, S3 Extended Request ID: xtL1ixsGM2/vsxJ+cZRHpkPZ23SMfP8hZZjQCQnp8oWGwdS2/aGfYgomihyqaDCQ 

你覺得在任何明顯的故障碼?

感謝, 斯特凡

回答

6

雖然你的使用情況健全,這是一個明顯的企圖實在的,我不認爲Multipart Upload API已被設計爲允許這一點,你實際上是違反了一道安全屏障:

上傳ID僅僅是一個標識符,用於協助將部件組裝在一起(即更像是臨時對象密鑰)而不是專用安全機制(見下文)。因此,您仍然需要適當的訪問憑據,但由於您致電AmazonS3Client(),其中構造了一個新的Amazon S3客戶端,該客戶端將向Amazon S3發出匿名請求,因此您的請求會產生相應的403訪問被拒絕

什麼,你正在努力實現通過Uploading Objects Using Pre-Signed URLs是可能的,儘管只是沒有多的功能,遺憾的是:

預標識的URL,您可以訪問的URL標識的對象, 提供的預簽名URL的創建者有權訪問該對象的 。也就是說,如果您收到一個預先簽名的URL以上傳 對象,則只有在 預簽名URL的創建者具有上載該對象所需的權限時,才能上傳該對象。

[...]如果你希望你的用戶/客戶可以上傳一個特定 對象預先簽署的網址 是有用的[...],但你並不需要他們有AWS安全 憑據或權限。當您創建一個預先簽名的URL時,您必須提供您的安全證書,指定一個存儲桶名稱,一個對象 鍵,一個HTTP方法(上傳對象的PUT)和一個到期日期 和時間。 [...]

的lenghty報價說明,爲什麼這樣可能系統需要更復雜的安全設計比「只是」發放的上傳ID(類似既可能出現在第一眼) 。

很顯然,人們希望能夠同時使用這兩個功能,但這似乎還不可用。

+1

非常感謝您的想法。即使因爲如果存儲桶可公開可以執行對S3的匿名請求,您的假設似乎也是如此,多分段上傳並不適合我的情況。而且那些預先簽名的URL不可用於多部分上傳太糟糕了。但是,我決定使用AWS IAM機制爲存儲桶設置writeonly策略,並將相應配置的新用戶的憑證存儲在applet中。從安全角度來看,應該沒問題。 – schneck

+0

@schneck:促進IAM只寫策略的確是一個很好的選擇,我已經把注意力放在了*你如何努力實現你的目標而不是實際的用例 - 你可以通過[製作請求使用IAM用戶臨時證書](http://docs.amazonwebservices.com/AmazonS3/latest/dev/AuthUsingTempSessionTokenJava.html)完全避免在您的小程序中存儲永久憑證。 –

+0

公共存儲桶是否存在危險,只有有人可以使用捲曲來發送垃圾信息?或者我錯過了什麼? – sethcall