在AWS Java SDK2中替换CloudFrontUrlSigner

时间:2019-06-06 06:52:19

标签: java aws-sdk amazon-cloudfront

我使用Java11。由于AWS Java SDK2支持Java 11,因此我使用SDK2。如何为s3键创建云前端URL。我可以为SDK 1.x版本获得许多示例,但对于SDK2无法获得。这就是在1.x中生成网址的方式

CloudFrontUrlSigner.getSignedURLWithCannedPolicy(url, keyPairId, privateKey, expires)

SDK 2.x版本中是否有其他替代方法或替代方法

1 个答案:

答案 0 :(得分:0)

我认为尚未实施。同时,从旧版本中剥离代码以执行相同的操作相当容易。

这是来自https://github.com/dashpradeep99/aws-sdk-java-code/blob/master/aws-java-sdk-cloudfront/src/main/java/com/amazonaws/services/cloudfront/util/SignerUtils.java

https://github.com/dashpradeep99/aws-sdk-java-code/blob/master/aws-java-sdk-cloudfront/src/main/java/com/amazonaws/services/cloudfront/CloudFrontUrlSigner.java

import software.amazon.awssdk.core.exception.SdkException;

import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.SecureRandom;
import java.security.Signature;
import java.security.SignatureException;
import java.util.Date;

import static java.util.concurrent.TimeUnit.MILLISECONDS;

public class AwsUtils {

  private static final SecureRandom srand = new SecureRandom();

  /**
   * Generates a signed url that expires after given date.
   * @param resourceUrlOrPath The url.
   * @param keyPairId The keypair id used to sign.
   * @param privateKey The private key.
   * @param dateLessThan The expire date/time.
   * @return A valid cloudwatch url.
   * @throws SdkException If any errors occur during the signing process.
   */
  public static String getSignedUrlWithCannedPolicy(String resourceUrlOrPath,
                                                    String keyPairId,
                                                    PrivateKey privateKey,
                                                    Date dateLessThan) throws SdkException {
    try {
      String cannedPolicy = buildCannedPolicy(resourceUrlOrPath, dateLessThan);
      byte[] signatureBytes = signWithSha1Rsa(cannedPolicy.getBytes(StandardCharsets.UTF_8), privateKey);
      String urlSafeSignature = makeBytesUrlSafe(signatureBytes);
      return resourceUrlOrPath
          + (resourceUrlOrPath.indexOf('?') >= 0 ? "&" : "?")
          + "Expires=" + MILLISECONDS.toSeconds(dateLessThan.getTime())
          + "&Signature=" + urlSafeSignature
          + "&Key-Pair-Id=" + keyPairId;
    } catch (InvalidKeyException e) {
      throw SdkException.create("Couldn't sign url", e);
    }
  }

  /**
   * Returns a "canned" policy for the given parameters.
   * For more information, see <a href=
   * "http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-signed-urls-overview.html"
   * >Overview of Signed URLs</a>.
   * @param resourceUrlOrPath The resource to grant access.
   * @param dateLessThan The expiration time.
   * @return the aws policy as a string.
   */
  public static String buildCannedPolicy(String resourceUrlOrPath,
                                         Date dateLessThan) {
    return "{\"Statement\":[{\"Resource\":\""
        + resourceUrlOrPath
        + "\",\"Condition\":{\"DateLessThan\":{\"AWS:EpochTime\":"
        + MILLISECONDS.toSeconds(dateLessThan.getTime())
        + "}}}]}";
  }

  /**
   * Signs the data given with the private key given, using the SHA1withRSA
   * algorithm provided by bouncy castle.
   * @param dataToSign The data to sign.
   * @param privateKey The private key.
   * @return A signature.
   * @throws InvalidKeyException if an invalid key was provided.
   */
  public static byte[] signWithSha1Rsa(byte[] dataToSign,
                                       PrivateKey privateKey) throws InvalidKeyException {
    Signature signature;
    try {
      signature = Signature.getInstance("SHA1withRSA");
      signature.initSign(privateKey, srand);
      signature.update(dataToSign);
      return signature.sign();
    } catch (NoSuchAlgorithmException | SignatureException e) {
      throw new IllegalStateException(e);
    }
  }

  /**
   * Converts the given data to be safe for use in signed URLs for a private
   * distribution by using specialized Base64 encoding.
   * @param bytes The bytes
   */
  public static String makeBytesUrlSafe(byte[] bytes) {
    byte[] encoded = java.util.Base64.getEncoder().encode(bytes);

    for (int i = 0; i < encoded.length; i++) {
      switch (encoded[i]) {
        case '+':
          encoded[i] = '-';
          continue;
        case '=':
          encoded[i] = '_';
          continue;
        case '/':
          encoded[i] = '~';
          continue;
        default:
          continue;
      }
    }
    return new String(encoded, StandardCharsets.UTF_8);
  }
}