【问题标题】:Creating a Signed URL for Google Cloud Storage为 Google Cloud Storage 创建签名 URL
【发布时间】:2018-10-03 05:54:37
【问题描述】:

我们有一个在 GCP 上运行的 ERP 应用程序。 对于下载超过三个月左右的数据,我们在 GCS 上上传文件。现在我想创建一个签名的 url,以便为最终用户提供有限的访问权限。 我一直在尝试这个。但我得到这个错误: 签名不匹配。请检查您的 Google 密钥。 谁能告诉我该怎么做?

private static final int EXPIRATION_TIME = 5;
private static final String BASE_URL = "https://storage.googleapis.com";
private static final  String httpVerb = "GET";
/*
 * private static final String BUCKET = "my_bucket"; private static final String
 * FOLDER = "folder";
 */
private final AppIdentityService identityService = AppIdentityServiceFactory.getAppIdentityService();

public String getSignedUrl(String bucket, final String fileName, String contentTpe) throws Exception {
    final long expiration = expiration();
    final String unsigned = stringToSign(bucket, expiration, fileName, contentTpe);
    final String signature = sign(unsigned);

    return new StringBuilder(BASE_URL).append("/").append(bucket).append("/").append(fileName)
            .append("?GoogleAccessId=").append(clientId()).append("&Expires=").append(expiration)
            .append("&Signature=").append(URLEncoder.encode(signature, "UTF-8")).toString();
}

private static long expiration() {
    final long unitMil = 1000l;
    final Calendar calendar = Calendar.getInstance();
    calendar.add(Calendar.MINUTE, EXPIRATION_TIME);
    final long expiration = calendar.getTimeInMillis() / unitMil;
    return expiration;
}

private String stringToSign(String bucket, final long expiration, String filename, String contentType) {
    final String contentMD5 = "";
    final String canonicalizedExtensionHeaders = "";
    final String canonicalizedResource = "/" + bucket + "/" + filename;      
    final String stringToSign = httpVerb + "\n"+ contentMD5 + "\n" + contentType + "\n" + expiration + "\n"
            + canonicalizedExtensionHeaders + canonicalizedResource;
    return stringToSign;
}

protected String sign(final String stringToSign) throws UnsupportedEncodingException {
    final SigningResult signingResult = identityService.signForApp(stringToSign.getBytes());
    final String encodedSignature = new String(Base64.encodeBase64(signingResult.getSignature()), "UTF-8");
    return encodedSignature;
}

protected String clientId() {
    return identityService.getServiceAccountName();
}

【问题讨论】:

    标签: google-cloud-storage


    【解决方案1】:

    URL 签名代码有点棘手,因为就其性质而言,除了看到错误之外,很难知道您做错了什么。有一些通用的提示可以使它更容易:

    首先,如果可能,请考虑使用 google-cloud 库中的 URL 签名函数。比如Java google-cloud library提供了一个Storage.signURL方法,你可以这样使用:

    URL signedUrl = storage.signUrl(
        BlobInfo.newBuilder(bucketName, blobName).build(),
        2, TimeUnit.DAYS);
    

    其次,如果您查看错误消息,您会注意到有一个<StringToSign> 部分。本节包含 GCS 将为其计算签名的确切字符串。确保您要签名的字符串与此字符串完全匹配。如果没有,那是你的问题。

    在您的代码的特定情况下,我没有发现问题,但可能是您在对字符串进行签名时包含了内容类型行,但 GET 请求不提供 Content-Type 标头。不过,这只是一个想法,因为我没有看到您调用 getSignedUrl。

    【讨论】:

      猜你喜欢
      • 2014-01-12
      • 2015-08-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多