【问题标题】:Create signed URL to put object in Google Storage创建签名 URL 以将对象放入 Google 存储
【发布时间】:2017-01-25 10:46:00
【问题描述】:

我正在努力创建签名 URL 以将文件上传到 Google 存储。 首先,我使用 JSON 密钥获取私钥和​​ clientId:

AuthCredentials.ServiceAccountAuthCredentials serviceAccountAuthCredentials = AuthCredentials.ServiceAccountAuthCredentials.createForJson(json_resource.getInputStream());
PrivateKey key = serviceAccountAuthCredentials.credentials().getPrivateKey();
Signature signer = Signature.getInstance("SHA256withRSA");
signer.initSign(key);

之后,创建要签名的字符串:

String upload_uri = "PUT\n\n" + expiration +
                "\n/" + bucketName + "/" + folderPath + "/" + fileName;

然后签名字符串:

signer.update(stringToSign.getBytes("UTF-8"));
byte[] rawSignature = signer.sign();
String signature = new String(Base64.encodeBase64(rawSignature, false), "UTF-8");

然后使用签名字符串组成 URL:

final String clientId = serviceAccountAuthCredentials.account();
String url = "http://storage.googleapis.com/" + 
             bucketName + "/" + folderPath + "/" + fileName +
             "?GoogleAccessId=" + clientId +
             "&Expires=" + expiration +
             "&Signature=" + URLEncoder.encode(signature, "UTF-8");

使用此 URL 我收到错误:

SignatureDoesNotMatch 我们计算的请求签名与您提供的签名不匹配。 检查您的 Google 密钥和签名方法。GET 1485340222074 /bucketName/fileName

【问题讨论】:

  • 您能否将您的 stringToSign 与同一 URL 上的 gsutil 等规范示例进行比较?对于初学者,我认为您在 PUT 之后缺少一个 \n (方法、md5 和内容类型应该有一个)。
  • 感谢@TravisHobrla 的建议。我试过了——没用。我也尝试添加 contentType - 也没有用。
  • 确保您的 StringToSign 遵循 correct format,确保您的过期时间在 Unix Epoch 中正确计算,并且您按照 guide 对其进行签名。还要确保使用 URL 的客户端也提供正确的标头,特别是您设置的内容类型。

标签: java google-app-engine google-cloud-storage google-cloud-platform


【解决方案1】:

您好,请从我这边检查以下工作代码。我觉得你缺少一些参数作为 get 或 token:`

    Calendar calendar = new GregorianCalendar();
            Long lExpireDate = Long.valueOf(calendar.getTime().getTime() + 7*86400000);//7 days validity
            String strExpireDate = fromDateLongtoStringISO8601(lExpireDate);

            String HTTP_Verb = "GET";
            String Content_MD5 = "";
            String Content_Type = "";//"image/jpeg";
            String Expiration = String.valueOf(lExpireDate/1000);
            String Canonicalized_Resource = "/"+bucketName+"/"+objectName;
            String StringToSign = HTTP_Verb + "\n" +
                    Content_MD5 + "\n" +
                    Content_Type + "\n" +
                    Expiration + "\n" +
                    Canonicalized_Resource;


            byte[] blob = StringToSign.getBytes();
            String BASE_URL = "https://storage.googleapis.com"+Canonicalized_Resource;

            ArrayList<String> scopes = new ArrayList<>();
            scopes.add(SQLAdminScopes.CLOUD_PLATFORM);
            appIdentity = AppIdentityServiceFactory.getAppIdentityService();
            AppIdentityService.GetAccessTokenResult accessToken = appIdentity.getAccessToken(scopes);

            AppIdentityService.SigningResult result = appIdentity.signForApp(blob);
            byte[] signatureByte = result.getSignature();
            String urlEncoded = com.google.api.client.util.Base64.encodeBase64String(signatureByte);
            String strURLBase64Encoded = URLEncoder.encode(urlEncoded);

            String GOOGLE_ACCESS_STORAGE_ID = appIdentity.getServiceAccountName();
            //GOOGLE_ACCESS_STORAGE_ID contains the email form of the client ID.

            String concatenatedURL = BASE_URL + "?GoogleAccessId=" + GOOGLE_ACCESS_STORAGE_ID
                    + "&Expires=" + strExpireDate
                    + "&access_token=" + URLEncoder.encode(accessToken.getAccessToken())
                    + "&Signature=" + strURLBase64Encoded;
            entity.setProperty(Media.URLD, concatenatedURL);

【讨论】:

  • 如果有人知道我们将签名的 url 与谷歌云存储调整功能 get_serving_url 相关联,请分享
  • @mp3 get_serving_url 属于一个 API,一旦您迁移到 App Engine Flex,该 API 将不可用。您仍然可以在 App Engine 标准中使用它。您需要做的是在文件上传后收到通知,然后使用 blobstoreService.createGsBlobKey 您将能够拥有一个与 get_serving_url 一起使用的 blob 密钥。如何在上传时获得通知?您可以使用 GCS 发布订阅通知 (cloud.google.com/storage/docs/pubsub-notifications)、Cloud Functions 或不太受欢迎的 webhook。
【解决方案2】:

我发现我必须在 StringToSign 中设置内容类型才能使 PUT 工作。在设置内容类型之前,我收到了与您收到的相同的错误消息。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-08-06
    • 2022-08-02
    • 1970-01-01
    • 1970-01-01
    • 2020-11-23
    • 2019-01-28
    • 1970-01-01
    • 2021-04-14
    相关资源
    最近更新 更多