我正在尝试使用签名的 URL 作为身份验证,直接通过 javascript 将图像的 base64 数据上传到 Google 存储,这显然是可以做到的。
根据developers.google.com/storage/docs/reference-methods#putobject,只需设置六个标头即可使其正常工作。同样对于标题“授权”,我试图在这里使用最后一个选项:
developer.google.com/storage/docs/reference-headers#authorization
这是“签名”developers.google.com/storage/docs/authentication#service_accounts
我唯一想使用 PHP 的就是获取签名。这是我一直在努力尝试但没有成功的事情。
PHP & JS 页面/代码
<?php
$theDate = Date(DATE_RFC822);
function signedURL( $filename, $bucket, $method = 'PUT' ) {
$signature = "";
$duration = 30;
$emailID = "980000000000-ytyertyr@developer.gserviceaccount.com";
$certs = array();
$priv_key = file_get_contents("9999999999999999999999999999-privatekey.p12");
if (!openssl_pkcs12_read($priv_key, $certs, 'notasecret')) { echo "Unable to parse the p12 file. OpenSSL error: " . openssl_error_string(); exit(); }
$expires = time() + $duration;
$to_sign = ( $method . "\n\n\n" . $expires . "\n" . "/" . $bucket . "/" . $filename );
$RSAPrivateKey = openssl_pkey_get_private($certs["pkey"]);
if (!openssl_sign( $to_sign, $signature, $RSAPrivateKey, 'sha256' ))
{
error_log( 'openssl_sign failed!' );
$signature = 'failed';
} else {
$signature = urlencode( base64_encode( $signature ) );
}
return (
'http://storage.googleapis.com/' . $bucket . '/' . $filename . '?GoogleAccessId=' . $emailID . '&Expires=' . $expires . '&Signature=' . $signature
);
openssl_free_key($RSAPrivateKey);
}
?>
<script>
var base64img = 'data:image/png;base64,AAABAAIAICA....snip...A';
var xhr = new XMLHttpRequest();
//PUT test - PUT status "(Canceled)" - OPTION status 200 (OK)
xhr.open("PUT", "<?php echo signedURL('test.png', 'mybucket'); ?>");
//xhr.setRequestHeader("Content-type", "image/png");
xhr.setRequestHeader("x-goog-acl", "public-read"); //try to set public read on file
xhr.setRequestHeader("Content-Length", base64img.length); // Chrome throws error (Refused to set unsafe header "Content-Length" )
xhr.send( base64img );
//GET test.txt temp file - working and returning 200 status (signing must be working ?)
/*
xhr.open("GET", "<?php echo signedURL('test.txt', 'mybucket', 'GET'); ?>");
xhr.send();
*/
//
</script>
Cors xml(似乎很好)-我仅在测试时设置了通配符,并且缓存/最大化时间较短
<?xml version="1.0" ?>
<CorsConfig>
<Cors>
<Origins>
<Origin>*</Origin>
</Origins>
<Methods>
<Method>GET</Method>
<Method>HEAD</Method>
<Method>OPTIONS</Method>
<Method>PUT</Method>
</Methods>
<ResponseHeaders>
<ResponseHeader>accept-encoding</ResponseHeader>
<ResponseHeader>cache-control</ResponseHeader>
<ResponseHeader>content-length</ResponseHeader>
<ResponseHeader>content-type</ResponseHeader>
<ResponseHeader>expect</ResponseHeader>
<ResponseHeader>if-modified-since</ResponseHeader>
<ResponseHeader>origin</ResponseHeader>
<ResponseHeader>range</ResponseHeader>
<ResponseHeader>referer</ResponseHeader>
<ResponseHeader>x-goog-acl</ResponseHeader>
<ResponseHeader>x-goog-api-version</ResponseHeader>
</ResponseHeaders>
<MaxAgeSec>900</MaxAgeSec>
</Cors>
</CorsConfig>
我已经在文件上测试了 GET 方法,现在返回 200 状态(\n\n - 修复)
更新:
与 Chrome 不同,在 Firefox 中查看它确实返回 403。