通过AWS Java SDK签署浏览器的S3上传请求
我有一个使用EmberJS构建的前端客户端,专门用来处理将文件直接上传到S3的问题。我陷入困境的地方是,在请求转到Amazon之前,我似乎无法使用后端服务器(JavaDropWizard微服务)对请求进行正确签名 我知道我可以创建一个通过AWS Java SDK签署浏览器的S3上传请求,java,amazon-web-services,amazon-s3,aws-sdk,Java,Amazon Web Services,Amazon S3,Aws Sdk,我有一个使用EmberJS构建的前端客户端,专门用来处理将文件直接上传到S3的问题。我陷入困境的地方是,在请求转到Amazon之前,我似乎无法使用后端服务器(JavaDropWizard微服务)对请求进行正确签名 我知道我可以创建一个generatePressignedUrlRequest,但是我使用的前端库特别想要从服务器返回一个json对象,所以我尝试将该generatePressignedUrlRequest拆分为一个对象 目前所有这些似乎都很好,但我缺少策略,因为我无法确定如何正确创建它
generatePressignedUrlRequest
,但是我使用的前端库特别想要从服务器返回一个json对象,所以我尝试将该generatePressignedUrlRequest
拆分为一个对象
目前所有这些似乎都很好,但我缺少策略,因为我无法确定如何正确创建它
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;
}
根据ember uploader的说明,我希望策略对象看起来像:
// 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签名版本4,但也不知道如何使用它
当我试图通过浏览器上传时,我从amazon上得到了一个403。我解决了这个问题,并为此编写了一个小的GUI模块。然后,在对后端的get请求中,从存储库类调用该函数
//资源
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());
}
}
公共类SignServiceProvider实现提供程序{
@注入
专用箭鱼配置;
@凌驾
公共签名服务get(){
返回新的SignServiceImpl(configuration.getAmazon());
}
}
我强烈建议您使用Jets3t。您能否详细说明Jets3t的哪些部分适用?我能看到的最接近文档的是S3 POST表单,这正是我想要的,但我不想通过后端服务呈现表单。我强烈建议使用后端创建至少一个签名,在这种情况下,您可以向服务器发送带有任何必要参数的AJAX POST,服务器将签名发送回,然后您将组合的表单和签名提供给客户端上载程序。在Jet3ts API中找不到允许我在不创建完整表单对象的情况下创建签名的任何地方。你能提供一个代码示例还是一个链接到API我可以在哪里做这个?Hiya,我处于类似的谜题中间,我把java的工作放在亚马逊提供的这些基础上。对于客户来说,这是一个两步流程。1) 客户端要求后端应用程序提供签名版本4“策略”。2)客户端使用该策略根据
public class SignServiceProvider implements Provider<SignService> {
@Inject
private SwordfishConfiguration configuration;
@Override
public SignService get() {
return new SignServiceImpl(configuration.getAmazon());
}
}