【问题标题】:Google Cloud Storage - Form upload (POST OBJECT), signature and policy problemsGoogle Cloud Storage - 表单上传(POST OBJECT)、签名和政策问题
【发布时间】:2014-01-08 11:20:15
【问题描述】:

我在尝试使用托管在 Google App Engine (GAE)、GWT 上的网页上的表单、使用 POST OBJECT 以及政策文档和签名将文件上传到 Google 云存储 (GCS) 时遇到了巨大的问题.

最大的问题;我没有收到任何关于错误的反馈。

首先。如果我根本不使用策略或签名,我可以将文件上传到 GCS,所以我假设错误在于该部分。代码见下文。

//Is used to get the policy as base64 and the signature (and converted to base64)
public String[] getPolicyAndSignature(String policy)
{
    try
    {
       KeyStore keystore = KeyStore.getInstance("PKCS12");
       keystore.load(new FileInputStream(new File("my_test_app/mykey.p12")), "notasecret".toCharArray());
       PrivateKey privateKey = (PrivateKey)keystore.getKey("privatekey", "notasecret".toCharArray());

       Signature signature = Signature.getInstance("SHA256withRSA");
       signature.initSign(privateKey);

       //is this wrong, should it be just: (?)
       //signature.update(policy.getBytes())
       signature.update(Base64Utils.toBase64(policy.getBytes()).getBytes());

       byte[] signatureBytes = signature.sign();
       byte[] policyBytes = policy.getBytes();

       return new String[]{Base64Utils.toBase64(policyBytes), Base64Utils.toBase64(signatureBytes)};
    }
    catch(Exception e)
    {
       System.out.println("Error: " + e.getMessage());
    }
    return null;
}

这是使用该功能的代码:

public TestUploader()
{
    VerticalPanel mainPanel = new VerticalPanel();
    final FormPanel formPanel = new FormPanel();
    formPanel.setWidget(mainPanel);

    FileUpload upload = new FileUpload();
    upload.setName("file");
    formPanel.setAction("http://sgacms.storage.googleapis.com");
    formPanel.setMethod(FormPanel.METHOD_POST);
    formPanel.setEncoding(FormPanel.ENCODING_MULTIPART);
    formPanel.getElement().setAttribute("accept-charset", "UTF-8");

    String keyString = "testing";
    String bucketString = "sgacms";
    Hidden key = new Hidden("key", keyString);
    Hidden bucket = new Hidden("bucket", bucketString);
    Hidden contentType = new Hidden("Content-Type", "image/jpeg");
    Hidden GoogleAccessID = new Hidden("GoogleAccessID", "517031602192-p8kn8m33vhmhg9horbif8mansmkilqle@developer.gserviceaccount.com");
    Hidden acl = new Hidden("acl", "bucket-owner-read");
    final Hidden policy = new Hidden("policy");
    final Hidden hiddenSignature = new Hidden("signature");

    String policyString =
        "{\"expiration\":\"2016-06-16T11:11:11Z\","+
            "\"conditions\":["+
                "[\"starts-with\",\"$key\",\"\"],"+
                "{\"acl\":\"bucket-owner-read\"},"+
                "{\"bucket\":\"sgacms\"},"+
                "[\"eq\",\"$Content-Type\",\"image/jpeg\"],"+
                "[\"content-length-range\",0,1000000]"+
            "]"+
        "}";

    String[] policyAndSignature = getPolicyAndSignature(policyString);
    policy.setValue(policyAndSignature[0]);
    hiddenSignature.setValue(policyAndSignature[1]);

    Button btn = new Button("Submit");

    mainPanel.add(btn); //submit
    mainPanel.add(key); //hidden
    mainPanel.add(bucket); //hidden
    mainPanel.add(contentType); //hidden
    mainPanel.add(GoogleAccessID); //hidden
    mainPanel.add(acl); //hidden
    mainPanel.add(policy);  //hidden
    mainPanel.add(hiddenSignature); //hidden
    mainPanel.add(upload); //file

    initWidget(formPanel);

    btn.addClickHandler(new ClickHandler() {
        @Override
        public void onClick(ClickEvent event) {
            formPanel.submit();
        }
    });
    formPanel.addSubmitCompleteHandler(new SubmitCompleteHandler() {
        @Override
        public void onSubmitComplete(SubmitCompleteEvent event) {
            log.severe("Submit results: " + event.getResults());
        }
    });
}

提交结果只是打印:null,当我失败时。而且因为我从来没有成功过,所以它永远不会打印任何其他东西。另一方面,如果我不使用任何策略和签名(即匿名上传),则提交结果将为空,并且文件将成功上传。

所以我不知道出了什么问题!任何帮助表示赞赏!谢谢!

编辑: 所以现在我终于能够得到一个错误响应,内容如下: "SignatureDoesNotMatch:我们计算的请求签名与您提供的签名不匹配。请检查您的 Google 密钥和签名方式"

【问题讨论】:

    标签: java google-app-engine gwt signature google-cloud-storage


    【解决方案1】:

    好的,我找到了问题的答案。

    我有点生气,这是一个如此“简单”的修复。正如您在我的问题中看到的那样,我正在使用 Base64Utils,它是“com.google.gwt.user.server.Base64Utils”包的一部分。我认为它在某种程度上有问题,要么我使用错误,要么它使用了一些默认的字符编码并忽略了它接收到的数据的编码,我根本不知道。我把它改成使用“org.apache.commons.codec.binary.Base64”包中的Base64,它似乎可以工作。

    (值得一提的是,我确实尝试将 Base64Utils 与 getBytes("UTF-8") 结合使用 - 但这也不起作用。)

    所以工作方法是这样的:

    public String[] getPolicyAndSignature(String policy)
    {
        try
        {
            String encodedPolicy = new String(Base64.encodeBase64(policy.getBytes()));
    
            KeyStore keystore = KeyStore.getInstance("PKCS12");
            keystore.load(new FileInputStream(new File("my_test_app/mykey.p12")), "notasecret".toCharArray());
            PrivateKey privateKey = (PrivateKey)keystore.getKey("privatekey", "notasecret".toCharArray());
    
            Signature signature = Signature.getInstance("SHA256withRSA");
            signature.initSign(privateKey);
            signature.update(encodedPolicy.getBytes());
    
            String encodedSignature = new String(Base64.encodeBase64(signature.sign(), false));
    
            return new String[]{encodedPolicy, encodedSignature};
        }
        catch(Exception e)
        {
            System.out.println("Error: " + e.getMessage());
        }
        return null;
    }
    

    【讨论】:

    • 你能解释一下如何用 html 形式和 java 来做吗?我正在尝试从 Google 应用引擎项目上传文件。最近两天我一直在寻找这种解决方案。等待您的回复@user2422321
    • 我的第一篇文章准确地展示了如何使用表单将文件上传到 Google Cloud Storage。我的第二篇文章(答案)显示了第一篇文章中要替换的内容。你不明白的是什么? :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-16
    • 1970-01-01
    • 2014-04-16
    • 1970-01-01
    • 2016-07-28
    • 2012-12-12
    相关资源
    最近更新 更多