Method call to get pre signed urls giving inconsistent results (S3)

I am using generatePresignedUrl method of AmazonS3Client class to get a pre-signed URL. However when the method is called in the same session as that of the upload of the file. it returns url of the form :

https://mp-dev.downloads.XYZ.com.s3.ap-south-1.amazonaws.com/certificate/404/17_04_2017/XYZ/ITHLUaXYPnMmHEUbK9L21KBneJQy7oJ1jw.zip?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20170417T090656Z&X-Amz-SignedHeaders=host&X-Amz-Expires=900&X-Amz-Credential=ASDFSFFGODQ%2F20170417%2Fap-south-1%2Fs3%2Faws4_request&X-Amz-Signature=9b2e112608c46cbeb16ff577b6e1321f889efsdfdsc850212251b231cb909d1942

But when I rerun my API and call the same method with the same params I get url of the form :

https://mp-dev.downloads.XYZ.com.s3.amazonaws.com/certificate/404/17_04_2017/XYZ/ITHLUaXYPnMmHEUbK9L21KBneJQy7oJ1jw.zip?AWSAccessKeyId=AKIAJFAFDTTISR4UHODQ&Expires=1492421420&Signature=CZuY1acATGUEEpoXN8aEQFXLX18%3D

First Url works fine but the second url results in :

The authorization mechanism you have provided is not supported. Please use AWS4-HMAC-SHA256.

I have tried to change configuration to use signature version 4 as per the following discussion :

The authorization mechanism you have provided is not supported. Please use AWS4-HMAC-SHA256

But doesn't work. Ask me if any additional info is required.

Endpoint to generate url :

@SkipAuthentication
  @GET
  @Path("/xyz")
  public String download(@QueryParam("cer") String objectKey) {
    return testService.test(objectKey).toString();
  }

Test method of service :

public URL test(String objectKey) {
    return awsDownloadService.generateDownloadUrl(objectKey, awsServer.getDownloadsBucketName());
  }

The generateDownloadUrl method is as follows :

  public URL generateDownloadUrl(String keyName, String bucketName) {
    LOG.info("generateDownloadUrl - {} {} {} {}>",accessKeyId, secretAccessKey, keyName, bucketName);
    BasicAWSCredentials awsCreds = new BasicAWSCredentials(accessKeyId, secretAccessKey);
    AmazonS3Client s3Client = new AmazonS3Client(awsCreds);

    Date expiration = new Date();
    long msec = expiration.getTime();
    msec += 1000 * 60 * 15; // 15 minutes.
    expiration.setTime(msec);
    GeneratePresignedUrlRequest generatePresignedUrlRequest = 
                  new GeneratePresignedUrlRequest(bucketName, keyName);
    generatePresignedUrlRequest.setMethod(HttpMethod.GET); // Default.
    generatePresignedUrlRequest.setExpiration(expiration);
    URL url = s3Client.generatePresignedUrl(generatePresignedUrlRequest);
    LOG.info("GeneratePreAuthenticatedUrl - url generated is <{}>",url);
    return url;
  }

When I upload the file using upload method and then call the end point to generate url it works fine but when I restart the api and call the end point to generate url, different url is returned as described earlier in the question.

Solution and new query:

I have solved the problem. Apparently , AmazonS3Client is deprecated. Making client this way works consistently :

AmazonS3ClientBuilder builder = AmazonS3ClientBuilder.standard().withCredentials(new AWSStaticCredentialsProvider(awsCreds));
    builder.setRegion(Regions.AP_SOUTH_1.getName());
    AmazonS3 s3client = builder.build();

Still, the behavior AmazonS3Client exhibited earlier is kind of odd. Can anybody provide explanation of the earlier behavior?


Apparently the AmazonS3Client class is deprecated in the latest JDKs. Creating client in the following manner solves the problem as it also takes region into account and hence attaches proper signature versions :

BasicAWSCredentials awsCreds = new BasicAWSCredentials(accessKeyId, secretAccessKey);
    AmazonS3ClientBuilder builder = AmazonS3ClientBuilder.standard().withCredentials(new AWSStaticCredentialsProvider(awsCreds));
    builder.setRegion(regionName);
    AmazonS3 s3client = builder.build();
链接地址: http://www.djcxy.com/p/39042.html

上一篇: AWS S3预定请求缓存

下一篇: 方法调用以获得预先签名的网址给出不一致的结果(S3)