EmberJS を使用して構築されたフロントエンド クライアント、特にember-uploaderを使用して、S3 へのファイルの直接アップロードを処理しました。私が行き詰まっているのは、Amazon に送信される前に、バックエンド サーバー (Java Dropwizard マイクロサービス) を使用してリクエストに正しく署名できないように見えることです。
を作成できることはわかっていますGeneratePresignedUrlRequest
が、使用しているフロントエンド ライブラリでは、サーバーから json オブジェクトを返す必要があるため、それをGeneratePresignedUrlRequest
オブジェクトに分割しようとしています。
現時点では問題ないように見えpolicy
ますが、正しく作成する方法をトレーニングできないため、行方不明です。
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;
}
valuePairs は GeneratePresignedUrlRequest
private String createSignedUrl() {
GeneratePresignedUrlRequest generatePresignedUrlRequest = new GeneratePresignedUrlRequest("test-bucket", "test.txt");
generatePresignedUrlRequest.setMethod(HttpMethod.PUT);
return amazonS3.generatePresignedUrl(generatePresignedUrlRequest).toString();
}
ember-uploader のwikiによると、ポリシー オブジェクトは次のようになります。
// 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
あちこち見ていますが、使い方もわかりません。
ブラウザ経由でアップロードしようとすると、Amazon から 403 が返されます。
私はこれを解決し、そのための小さな guice モジュールを作成しました。これは、バックエンドへの get リクエストで Repository クラスから呼び出されます。
// 資源
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 interface SignService {
String signRequest(String contentType);
}
// モジュール
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());
}
}
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加