2017-04-04 14 views
0

EmberJSを使用してフロントエンドクライアントを構築しました。具体的にはember-uploaderを使用して、S3に直接ファイルをアップロードします。私が立ち往生しているところでは、バックエンドサーバー(Java Dropwizardマイクロサービス)を使ってAmazonに行く前に、そのリクエストに正しく署名することができないようです。AWS-Java SDK経由でブラウザにS3のアップロードリクエストを送信

私はGeneratePresignedUrlRequestを作成できますが、私が使用しているフロントエンドライブラリでは、jsonオブジェクトがサーバから戻ってくることを望んでいるので、そのオブジェクトをGeneratePresignedUrlRequestに分割しようとしています。

現時点ではすべて問題なく表示されますが、正しく作成する方法を練習できないため、policyが見つかりません。

valuePairs私はポリシーオブジェクトはのようなものを見てみたい燃えさし-アップローダーの wikiによると GeneratePresignedUrlRequest

private String createSignedUrl() { 
    GeneratePresignedUrlRequest generatePresignedUrlRequest = new GeneratePresignedUrlRequest("test-bucket", "test.txt"); 
    generatePresignedUrlRequest.setMethod(HttpMethod.PUT); 

    return amazonS3.generatePresignedUrl(generatePresignedUrlRequest).toString(); 
} 

から来ている

private SignRequestObject createSignRequestObject(List<NameValuePair> valuePairs) { 
    SignRequestObject request = new SignRequestObject(); 

    request.setKey("test.txt"); 
    request.setBucket("test-bucket"); 
    request.setPolicy("?"); 

    for (NameValuePair pairs : valuePairs) { 
     if (pairs.getName().equals("X-Amz-Credential")) { 
      request.setCredentials(pairs.getValue()); 
     } 

     if (pairs.getName().equals("X-Amz-Signature")) { 
      request.setSignature(pairs.getValue()); 
     } 

     if (pairs.getName().equals("X-Amz-Algorithm")) { 
      request.setAlgorithm(pairs.getValue()); 
     } 

     if (pairs.getName().equals("X-Amz-Date")) { 
      request.setDate(pairs.getValue()); 
     } 
    } 

    return request; 
} 

:私はしようとするべき

// Ruby example, but shouldn't matter 
     { 
      expiration: @expires, 
      conditions: [ 
      { bucket: 'sandbox' }, 
      { acl: 'public-read' }, 
      { expires: @expires }, 
      { success_action_status: '201' }, 
      [ 'starts-with', '$key', '' ], 
      [ 'starts-with', '$Content-Type', '' ], 
      [ 'starts-with', '$Cache-Control', '' ], 
      [ 'content-length-range', 0, 524288000 ] 
      ] 
    ) 

これを自分で構築するか、aws-sdkにはこのためのメソッドがありますか?私はAWS Signature Version 4を見ていますが、それを使う方法もわかりません。

ブラウザ経由でアップロードしようとすると、私はアマゾンから403を手に入れています。

+0

私は強くJets3tを使用することをお勧めします。 – chrylis

+0

jets3tのどの部分を拡張できますか?私がドキュメントを見て見ることができる最も近いのは、S3 POSTフォームです。バックエンドサービスを介してフォームをレンダリングしたくないのですが、 –

+0

バックエンドを使用して作成することを強く推奨します。少なくとも署名が必要な場合は、必要なパラメータを指定してAJAXポストをサーバに送信し、サーバは署名を送り返してから、結合したフォームと署名をクライアント側のアップローダに送ります。 – chrylis

答えて

0

私はこれを解決し、小さなguiceモジュールを書きました。これは、バックエンドへのget要求でRepositoryクラスから呼び出されます。 //サービス

public interface SignService { 
    String signRequest(String contentType); 
} 

//リソース

public class SignResource { 

    private final SignRepository repository; 

    @Inject 
    public SignResource(SignRepository repository) { 
     this.repository = repository; 
    } 

    @GET 
    public Response signPOST(@QueryParam("type") String type) { 
     String signRequest = repository.signRequest(type); 
     return Response.status(Response.Status.OK).entity(signRequest).build(); 
    } 
} 

//リポジトリ

public class SignRepository { 

    @Inject 
    private SignService signService; 

    public SignRepository() { 
    } 

    public String signRequest(String contentType) { 
     return signService.signRequest(contentType); 
    } 
} 

//実装

public class SignServiceImpl implements SignService { 

    private String awsBucket; 
    private String awsAccessKey; 
    private String awsSecretKey; 

    SignServiceImpl(AmazonConfiguration amazon) { 
     awsSecretKey = amazon.getSecret(); 
     awsAccessKey = amazon.getAccess(); 
     awsBucket = amazon.getBucket(); 
    } 

    @Override 
    public String signRequest(String contentType) { 
     final String randomFileName = createRandomName(); 

     String policy = createPolicy(randomFileName, contentType); 

     SignRequest signRequest = new SignRequest(); 
     signRequest.setAwsAccessKeyId(awsAccessKey); 
     signRequest.setPolicy(policy); 
     signRequest.setSignature(ServiceUtils.signWithHmacSha1(awsSecretKey, policy)); 
     signRequest.setBucket(awsBucket); 
     signRequest.setKey(randomFileName); 
     signRequest.setAcl("public-read"); 
     signRequest.setContentType(contentType); 
     signRequest.setExpires(createExpireTime().toString()); 
     signRequest.setSuccessActionStatus("201"); 

     return createJsonString(signRequest); 
    } 

    private String createPolicy(String randomFileName, String contentType) { 
     try { 
      String[] conditions = { 
       S3Service.generatePostPolicyCondition_Equality("bucket", awsBucket), 
       S3Service.generatePostPolicyCondition_Equality("key", randomFileName), 
       S3Service.generatePostPolicyCondition_Equality("acl", "public-read"), 
       S3Service.generatePostPolicyCondition_Equality("expires", createExpireTime().toString()), 
       S3Service.generatePostPolicyCondition_Equality("content-Type", contentType), 
       S3Service.generatePostPolicyCondition_Equality("success_action_status", "201"), 
       S3Service.generatePostPolicyCondition_AllowAnyValue("cache-control") 
      }; 

      String policyDocument = "{\"expiration\": \"" + ServiceUtils.formatIso8601Date(createExpireTime()) + "\", \"conditions\": [" + ServiceUtils.join(conditions, ",") + "]}"; 

      return ServiceUtils.toBase64(policyDocument.getBytes(Constants.DEFAULT_ENCODING)); 
     } catch (UnsupportedEncodingException e) { 
      e.printStackTrace(); 
     } 

     return null; 
    } 

    private String createRandomName() { 
     return UUID.randomUUID().toString(); 
    } 

    private Date createExpireTime() { 
     Calendar cal = Calendar.getInstance(); 
     cal.add(Calendar.HOUR, 24); 

     return cal.getTime(); 
    } 

    private String createJsonString(SignRequest request) { 
     ObjectMapper mapper = new ObjectMapper(); 
     String json = null; 

     try { 
      json = mapper.writeValueAsString(request); 
     } catch (JsonProcessingException e) { 
      e.printStackTrace(); 
     } 

     return json; 
    } 
} 

//モジュール

public class SignServiceModule extends AbstractModule { 

    @Override 
    protected void configure() { 
     bind(SignService.class).toProvider(SignServiceProvider.class).asEagerSingleton(); 
    } 
} 

//プロバイダ

public class SignServiceProvider implements Provider<SignService> { 

    @Inject 
    private SwordfishConfiguration configuration; 

    @Override 
    public SignService get() { 
     return new SignServiceImpl(configuration.getAmazon()); 
    } 
} 
関連する問題