2

我正在使用 AppEngine 中的 Google Cloud Storage,并尝试使用 POST 表单将文件上传到 GCS。我遇到的问题是签署政策文件所需的步骤。我可以轻松地获取 client_secret,它是client_secrets.jsonAPI 控制台给我的字符串。但是,为了创建签名,我需要将该字符串转换为PrivateKey对象。这是我的代码的样子:

//create the policy document and encode it
String policyDocument = ...  //omitted for brevity
String encodedPolicy = Base64.encodeString(policyDocument);

//sign using SHA256 with RSA
String secretKey = ... //I fetch this from client_secrets.json
Signature sig = Signature.getInstance("SHA256withRSA");
sig.initSign(secretKey); //THIS IS THE PROBLEM!  
sig.update(encodedPolicy.getBytes("UTF-8"));        
String signature = new String(Base64.encode(sig.sign()));

//put the values in the request attributes so we can fetch them from a JSP
req.setAttribute("policy", encodedPolicy);
req.setAttribute("signature", signature);

如上所述,我的问题在于

sig.initSign(secretKey); //THIS IS THE PROBLEM!  

secretKey是一个字符串。 Signature.initSign()期望 aPrivateKey或其后代对象之一。如何将字符串中的字符串转换为client_secrets.json可以传递的 PrivateKey(或派生)对象Signature.initSign

任何帮助将不胜感激。谢谢

好的,这就是我现在的位置。我尝试了以下建议,所有文档都敦促我使用从 Google API 控制台下载的 client_secrets.json 文件中的 client_secret,而不是服务帐户。此外,我正在尝试构建用户上传的示例,而不是服务帐户。

我在另一个页面上找到了以下代码:

public static String signPolicyDocument(String policyDocument, String secret) {     
try {
        Mac mac = Mac.getInstance("HmacSHA256");
        byte[] secretBytes = secret.getBytes();
        SecretKeySpec signingKey = new SecretKeySpec(secretBytes, "HmacSHA256");
        mac.init(signingKey);
        byte[] signedSecretBytes = mac.doFinal(policyDocument.getBytes());          
        return new String(Base64.encode(signedSecretBytes));
    } catch (InvalidKeyException e) {
        throw new RuntimeException(e);
    } catch (NoSuchAlgorithmException e) {
        throw new RuntimeException(e);
    }

它让我完成了整个过程……直到我提交结果表格。然后我得到以下响应:

The request signature we calculated does not match the signature you provided. Check your Google secret key and signing method.

它在寻找什么签名方法?

4

3 回答 3

1

这是我认为你需要做的:

KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
sig.initSign(privateKey);

keyBytes变量应包含一个byte[]数组,其中包含您的服务帐户密钥文件

于 2013-02-26T20:39:25.943 回答
1

这个问题的最终答案就像战争游戏的结论一样。正如 WOPR 所说,“一场奇怪的比赛……获胜的唯一方法就是不玩。” 避免签署和策略文档以及所有这些废话,并使用 blobstore。

(见: https ://developers.google.com/appengine/docs/java/blobstore/overview#using-blobstore-with-gcs )

这很容易实现;当您像这样创建临时 blobstore 上传 URL 时:

    //open the blobstore service and create the upload url
    BlobstoreService bs = BlobstoreServiceFactory.getBlobstoreService();        
    String uploadUrl = bs.createUploadUrl("/display",
            UploadOptions.Builder.withGoogleStorageBucketName(bucket));

这种方法的缺点是对象名称将是您无法识别的字符串。您可以打开 blobstore 查看器并在 blobstore 中按文件名查看您的对象,但在 GCS 中,其对象名称将是 gobbledygook。(可能是哈希?随机分配的 ID)?

于 2013-02-28T00:19:33.500 回答
0

要将文件从 Appengine 上传到 GCS,您可以使用 blobstore Api。按照将Blobstore 与 GCS 结合使用中所述的步骤进行操作。优点是不用担心按键,代码也简单多了。

于 2013-02-27T18:42:14.683 回答