2012-01-24 33 views
5

Tôi đang cố tải lên tệp bằng SDK Java của Amazon, thông qua tải lên nhiều phần. Ý tưởng là chuyển một id tải lên thành một applet, trong đó đặt các phần của tệp vào một nhóm chỉ đọc. Đi theo cách này, tôi tránh lưu trữ thông tin đăng nhập AWS trong applet.Đặt tệp vào Amazon S3 bằng cách sử dụng tính năng tải lên nhiều phần

Trong các thử nghiệm của mình, tôi tạo id tải lên có boto (python) và lưu trữ tệp vào thùng. Điều đó hoạt động tốt.

Applet của tôi bị "Truy cập 403 bị từ chối" từ S3 và tôi không biết tại sao.

Dưới đây là mã của tôi (mà là một phần lấy từ 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)); 
} 

Trong nhật ký Applet debug, tôi tìm thấy điều này, thì:

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 

Bạn có thấy bất kỳ thất bại rõ ràng trong mã?

Cảm ơn, Stefan

Trả lời

6

Trong khi trường hợp sử dụng của bạn là âm thanh và điều này là một nỗ lực rõ ràng trên thực tế, tôi không nghĩ rằng Multipart Upload API đã được thiết kế để cho phép điều này và bạn đang thực sự vi phạm một hàng rào an ninh:

ID tải lên chỉ là số nhận dạng để hỗ trợ API tải lên nhiều phần trong việc lắp ráp các phần với nhau (ví dụ như khóa đối tượng tạm thời) không phải là cơ chế bảo mật chuyên dụng (xem bên dưới). Do đó bạn vẫn yêu cầu thông tin truy cập thích hợp tại chỗ, nhưng vì bạn đang gọi AmazonS3Client(), trong đó Xây dựng một ứng dụng khách Amazon S3 mới sẽ thực hiện yêu cầu ẩn danh tới Amazon S3, yêu cầu của bạn mang lại 403 Truy cập bị từ chối.

Những gì bạn đang cố gắng để đạt có thể qua Uploading Objects Using Pre-Signed URLs, mặc dù chỉ mà không có chức năng nhiều phần dữ liệu, không may:

URL trước khi ký kết cung cấp cho bạn truy cập vào các đối tượng xác định trong URL, với điều kiện người tạo URL được ký trước có quyền truy cập vào đối tượng đó để truy cập vào đối tượng đó . Tức là, nếu bạn nhận được URL được ký trước để tải lên một đối tượng, bạn chỉ có thể tải lên đối tượng nếu người tạo của URL được ký trước có các quyền cần thiết để tải lên đối tượng đó.

[...] URL được ký trước rất hữu ích nếu bạn muốn người dùng/khách hàng của bạn có thể tải lên đối tượng cụ thể [...], nhưng bạn không yêu cầu họ có bảo mật AWS thông tin đăng nhập hoặc quyền. Khi bạn tạo URL được ký trước, bạn phải cung cấp thông tin đăng nhập bảo mật của mình, chỉ định tên nhóm đối tượng khóa, phương thức HTTP (PUT đối tượng tải lên) và ngày hết hạn và thời gian. [...]

Các quote lenghty minh họa, tại sao một hệ thống như thế này khả năng cần một thiết kế an ninh phức tạp hơn 'chỉ' giao ra một ID upload (như tương tự như cả hai có thể xuất hiện ngay từ cái nhìn đầu tiên) .

Rõ ràng một người muốn có thể sử dụng cả hai tính năng cùng nhau, nhưng điều này dường như chưa khả dụng.

+1

Cảm ơn rất nhiều vì những suy nghĩ của bạn. Ngay cả khi có thể thực hiện các yêu cầu ẩn danh đối với S3 nếu thùng công khai có sẵn, giả định của bạn có vẻ đúng, việc tải lên nhiều phần không chỉ được thực hiện cho trường hợp của tôi. Và các URL được ký trước không có sẵn để tải lên nhiều phần tử quá xấu. Tuy nhiên, tôi quyết định sử dụng cơ chế AWAM IAM để thiết lập chính sách viết-viết cho nhóm và lưu trữ thông tin xác thực cho người dùng mới được cấu hình tương ứng trong applet. Từ quan điểm bảo mật, nó sẽ ổn thôi. – schneck

+0

@schneck: Tạo thuận lợi cho chính sách chỉ viết IAM là một lựa chọn tuyệt vời, tôi đã tập trung quá nhiều vào * cách * bạn đang cố gắng đạt được mục tiêu của mình hơn là trường hợp sử dụng thực tế - bạn có thể thực hiện điều đó hơn nữa bằng cách Yêu cầu Sử dụng thông tin đăng nhập tạm thời của người dùng IAM] (http://docs.amazonwebservices.com/AmazonS3/latest/dev/AuthUsingTempSessionTokenJava.html) để tránh hoàn toàn việc lưu trữ thông tin đăng nhập vĩnh viễn trong applet của bạn. –

+0

Không phải là mối nguy hiểm với một thùng chỉ công khai, chỉ là một người nào đó có thể spam thùng của bạn bằng cách sử dụng không có gì hơn curl? Hay tôi đang thiếu một cái gì đó? – sethcall

Các vấn đề liên quan