0

我一直在尝试使用 HTML 表单通过 POST 将文件上传到 GCE,尽管到目前为止我一直收到以下错误消息:

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

这是我在名为 gcs.php 的文件中的示例代码:

 <?php
       $bucketName = “BUCKET_NAME";
       $accessId = “ACCESS_ID";

function generateGcsSignature($bucketName, $filePath, $params=array()){

         if($params['ttl'] < 300) {
          $params['ttl'] = 300; // 5 mins
        }

        $expiry = time() + $params['ttl'];

        $valid_methods = array("PUT","GET", "POST");
        $method = "";
        if(!isset($params["method"]) || !in_array($params['method'], $valid_methods))
           $method = "GET";
        else
            $method = $params["method"];

        $parts = array($params['method'], "", "", $expiry, "/$bucketName/$filePath");
        $stringPolicy = implode("\n", $parts);

        $fp = fopen("../gcs-key.pem", "r");
        $priv_key = fread($fp, 8192);
        fclose($fp);
        $pkeyid = openssl_get_privatekey($priv_key, "");

        $signSuccess = openssl_sign($stringPolicy, $signature, $pkeyid, 'sha256' );
        $openssl_error = openssl_error_string();

        if ($signSuccess) {
           $signature = urlencode( base64_encode( $signature ) );
           global $accessId;
           return $signature;
        }

}

function generatePolicy(){

         $policy = '
         {"expiration": "'.date("c", time()+300).'",
           "conditions": [
                ["starts-with", "key", "" ],
                {"acl": "bucket-owner-read" },
                {"bucket": "BUCKET_NAME"},
                {"success_action_redirect": "http://www.example.com/success_notification.html" },
                ["eq", "Content-Type", "image/jpeg" ],
                ["content-length-range", 0, 1000000]
           ]
         }';

         $policy = base64_encode(trim($policy));

         $fp = fopen("../gcs-key.pem", "r");
        $priv_key = fread($fp, 8192);
        fclose($fp);
        $pkeyid = openssl_get_privatekey($priv_key, "");

        $signSuccess = openssl_sign($policy, $signature, $pkeyid, 'sha256' );
        $openssl_error = openssl_error_string();

        if ($signSuccess) {
           $signature = urlencode( base64_encode( $signature ) );
           global $accessId;
           return $signature;
        }

}


       $signature = generateGcsSignature($bucketName, $key, array("ttl" => "300", "method" => "POST"));
       $policy = generatePolicy();
    ?>
    <form action="http://<?=$bucketName?>.storage.googleapis.com" method="post" enctype="multipart/form-data">
    <input type="text" name="key" value="asdfasdf.jpg">
    <input type="hidden" name="bucket" value="<?=$bucketName?>">
    <input type="hidden" name="Content-Type" value="image/jpeg">
    <input type="hidden" name="GoogleAccessId" value="<?=$accessId?>">
    <input type="hidden" name="acl" value="bucket-owner-read">
    <input type="hidden" name="success_action_redirect" value="http://www.example.com/success_notification.html">
    <input type="hidden" name="policy" value="<?=$policy?>"/>
    <input type="hidden" name="signature" value="<?=$signature?>">

    <input name="file" type="file">
    <input type="submit" value="Upload">
    </form>

请注意,BUCKET_NAME 和 ACCESS_ID 在我的代码中设置为正确的值,我可以确认这一点,因为我已经能够对指定存储桶中的文件执行 GET。

我一直在寻找解决我这个问题的方法,但到目前为止没有运气,所以我想我会在这里发布我的代码,希望有人能指出我做错了什么。我会很感激我能得到的任何帮助!

4

1 回答 1

0

与 POST 表单一起使用的签名参数不共享 GET 和 PUT 请求所做的常见 HTTP_verb + MD5 + type + Expiration + etc 模式。

相反,当使用带有策略文档的 POST 请求时,您签署策略文档并且仅签署策略文档。请参阅https://developers.google.com/storage/docs/reference-methods#policydocument并向下滚动到“以下伪代码结合上述步骤以创建您的签名”开头的位。

步骤是:

Policy = Base-64-Encoding-Of(PolicyDocument)
MessageDigest = SHA256withRSA(SecretKey, Policy)
Signature = Base64-Encoding-Of(MessageDigest)

好问题。对困惑感到抱歉!

于 2014-07-23T06:44:54.227 回答