2014-01-08 67 views
1

我在嘗試使用Google App Engine上託管的網頁上的表單將文件上傳到Google Cloud Storage(GCS)時遇到了巨大問題( GAE),GWT,使用POST OBJECT和政策文件和簽名。Google雲端存儲 - 表單上傳(POST OBJECT),簽名和政策問題

所有最大的問題;我對什麼是錯誤沒有任何反饋。

首先。如果我根本不使用策略或簽名,我可以將文件上傳到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", "[email protected]account.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()); 
     } 
    }); 
} 

的結果提交簡單的打印:空,當我失敗。而且由於我從來沒有成功,所以從不打印其他東西如果我另一方面沒有使用策略並且沒有簽名(換言之匿名上傳),則提交結果將爲空,並且文件將成功上傳。

所以我無法弄清楚什麼是錯的!任何幫助表示讚賞!謝謝!

編輯: 所以,現在我終於能夠得到一個錯誤響應,其表示如下: 「SignatureDoesNotMatch:我們出的要求籤名不匹配您提供的簽名檢查你的谷歌祕密密鑰和簽名方法「

回答

2

好吧,所以我找到了我的問題的答案。

我有點生氣,這是一個「簡單」的修復。正如你在我的問題中看到的,我使用的是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; 
} 
+0

可以請你解釋一下如何在html窗體和java中完成它?我試圖從Google應用引擎項目上傳文件。過去兩天我一直在尋找這種解決方案。等待您的回覆@ user2422321 – Sreekanth

+0

我的第一篇文章顯示瞭如何使用表單將文件上傳到Google Cloud Storage。我的第二篇文章(答案)顯示了第一篇文章中要替換的內容。你不明白的是什麼? :) – Whyser

相關問題