mirror of https://github.com/apache/jclouds.git
URL encode string to sign.
As recommended at http://s3.amazonaws.com/doc/s3-developer-guide/RESTAuthentication.html: "You can also send a signature as a URL-encoded query-string parameter in the URL for the request." Also deals with some of the craziness of URL encoding/decoding in jclouds. References JCLOUDS-200
This commit is contained in:
parent
70af0ea5ab
commit
675c649cb6
|
@ -19,6 +19,8 @@ package org.jclouds.aws.s3.blobstore;
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
import static org.jclouds.blobstore.util.BlobStoreUtils.cleanRequest;
|
import static org.jclouds.blobstore.util.BlobStoreUtils.cleanRequest;
|
||||||
|
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.net.URLEncoder;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
@ -35,6 +37,7 @@ import org.jclouds.s3.blobstore.S3BlobRequestSigner;
|
||||||
import org.jclouds.s3.blobstore.functions.BlobToObject;
|
import org.jclouds.s3.blobstore.functions.BlobToObject;
|
||||||
import org.jclouds.s3.filters.RequestAuthorizeSignature;
|
import org.jclouds.s3.filters.RequestAuthorizeSignature;
|
||||||
|
|
||||||
|
import com.google.common.base.Charsets;
|
||||||
import com.google.common.base.Supplier;
|
import com.google.common.base.Supplier;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.net.HttpHeaders;
|
import com.google.common.net.HttpHeaders;
|
||||||
|
@ -91,10 +94,23 @@ public class AWSS3BlobRequestSigner extends S3BlobRequestSigner<AWSS3AsyncClient
|
||||||
Date date = dateService.rfc1123DateParse(dateString);
|
Date date = dateService.rfc1123DateParse(dateString);
|
||||||
String expiration = String.valueOf(TimeUnit.MILLISECONDS.toSeconds(date.getTime()) + timeInSeconds);
|
String expiration = String.valueOf(TimeUnit.MILLISECONDS.toSeconds(date.getTime()) + timeInSeconds);
|
||||||
HttpRequest.Builder<?> builder = request.toBuilder().replaceHeader(HttpHeaders.DATE, expiration);
|
HttpRequest.Builder<?> builder = request.toBuilder().replaceHeader(HttpHeaders.DATE, expiration);
|
||||||
final String signature = authSigner.sign(authSigner.createStringToSign(builder.build()));
|
String stringToSign = authSigner.createStringToSign(builder.build());
|
||||||
return builder.addQueryParam(TEMPORARY_SIGNATURE_PARAM, signature)
|
// We MUST encode the signature because addQueryParam internally _always_ decodes values
|
||||||
.addQueryParam(HttpHeaders.EXPIRES, expiration)
|
// and if we don't encode the signature here, the decoding may change the signature. For e.g.
|
||||||
|
// any '+' characters in the signature will be converted to space ' ' on decoding.
|
||||||
|
String signature = authSigner.sign(stringToSign);
|
||||||
|
try {
|
||||||
|
signature = URLEncoder.encode(signature, Charsets.UTF_8.name());
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
throw new IllegalStateException("Bad encoding on input: " + signature, e);
|
||||||
|
}
|
||||||
|
HttpRequest ret = builder.addQueryParam(HttpHeaders.EXPIRES, expiration)
|
||||||
.addQueryParam("AWSAccessKeyId", identity)
|
.addQueryParam("AWSAccessKeyId", identity)
|
||||||
|
// Signature MUST be the last parameter because if it isn't, even encoded '+' values in the
|
||||||
|
// signature will be converted to a space by a subsequent addQueryParameter.
|
||||||
|
// See HttpRequestTest.testAddBase64AndUrlEncodedQueryParams for more details.
|
||||||
|
.addQueryParam(TEMPORARY_SIGNATURE_PARAM, signature)
|
||||||
.build();
|
.build();
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,8 @@ import com.google.inject.Module;
|
||||||
*/
|
*/
|
||||||
@Test(groups = "unit", testName = "AWSS3BlobSignerExpectTest")
|
@Test(groups = "unit", testName = "AWSS3BlobSignerExpectTest")
|
||||||
public class AWSS3BlobSignerExpectTest extends S3BlobSignerExpectTest {
|
public class AWSS3BlobSignerExpectTest extends S3BlobSignerExpectTest {
|
||||||
|
private static final String DATE = "Thu, 05 Jun 2008 16:38:19 GMT";
|
||||||
|
|
||||||
public AWSS3BlobSignerExpectTest() {
|
public AWSS3BlobSignerExpectTest() {
|
||||||
provider = "aws-s3";
|
provider = "aws-s3";
|
||||||
}
|
}
|
||||||
|
@ -43,9 +45,9 @@ public class AWSS3BlobSignerExpectTest extends S3BlobSignerExpectTest {
|
||||||
protected HttpRequest getBlobWithTime() {
|
protected HttpRequest getBlobWithTime() {
|
||||||
return HttpRequest.builder().method("GET")
|
return HttpRequest.builder().method("GET")
|
||||||
.endpoint("https://container.s3.amazonaws.com/name" +
|
.endpoint("https://container.s3.amazonaws.com/name" +
|
||||||
"?Signature=Y4Ac4sZfBemGZmgfG78F7IX%20IFg%3D&Expires=1212683902&AWSAccessKeyId=identity")
|
"?Expires=1212683902&AWSAccessKeyId=identity&Signature=Y4Ac4sZfBemGZmgfG78F7IX%2BIFg%3D")
|
||||||
.addHeader("Host", "container.s3.amazonaws.com")
|
.addHeader("Host", "container.s3.amazonaws.com")
|
||||||
.addHeader("Date", "Thu, 05 Jun 2008 16:38:19 GMT").build();
|
.addHeader("Date", DATE).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -60,10 +62,10 @@ public class AWSS3BlobSignerExpectTest extends S3BlobSignerExpectTest {
|
||||||
protected HttpRequest putBlobWithTime() {
|
protected HttpRequest putBlobWithTime() {
|
||||||
return HttpRequest.builder().method("PUT")
|
return HttpRequest.builder().method("PUT")
|
||||||
.endpoint("https://container.s3.amazonaws.com/name" +
|
.endpoint("https://container.s3.amazonaws.com/name" +
|
||||||
"?Signature=genkB2vLxe3AWV/bPvRTMqQts7E%3D&Expires=1212683902&AWSAccessKeyId=identity")
|
"?Expires=1212683902&AWSAccessKeyId=identity&Signature=genkB2vLxe3AWV/bPvRTMqQts7E%3D")
|
||||||
.addHeader("Expect", "100-continue")
|
.addHeader("Expect", "100-continue")
|
||||||
.addHeader("Host", "container.s3.amazonaws.com")
|
.addHeader("Host", "container.s3.amazonaws.com")
|
||||||
.addHeader("Date", "Thu, 05 Jun 2008 16:38:19 GMT").build();
|
.addHeader("Date", DATE).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -86,7 +88,7 @@ public class AWSS3BlobSignerExpectTest extends S3BlobSignerExpectTest {
|
||||||
@Override
|
@Override
|
||||||
@TimeStamp
|
@TimeStamp
|
||||||
protected String provideTimeStamp(@TimeStamp Supplier<String> cache) {
|
protected String provideTimeStamp(@TimeStamp Supplier<String> cache) {
|
||||||
return "Thu, 05 Jun 2008 16:38:19 GMT";
|
return DATE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue