Die Idee, diese Bibliothek zu schreiben, entstand, als ich das kostenlose Oracle Cloud Infrastructure- Angebot voll ausnutzen wollte , nämlich 10 GB Objektspeicher und 10 TB ausgehenden Datenverkehr pro Monat. Der Unterschied zu AWS S3 ist enorm . Leider verfügt Oracle Cloud nicht über ein SDK für die immer noch beliebteste Programmiersprache für die Website-Entwicklung. Die gute Nachricht ist, dass der Dienst teilweise mit Amazon S3 kompatibel ist. Dies bedeutet, dass Sie vorhandene und gut dokumentierte Entwicklertools verwenden können , auch für PHP.
Für diejenigen, die den Code sehen möchten, willkommen unter https://github.com/hitrov/oci-api-php-request-sign .
Mit den verfügbaren Tools können Sie nahezu alle erdenklichen Vorgänge ausführen - zum Erstellen, Lesen und Löschen von Buckets und Objekten (Dateien). Papierkörbe können sowohl öffentlich (mit oder ohne Auflistung von Dateien) als auch privat sein. Es ist möglich, Dateien in einen privaten Warenkorb hochzuladen, der nur eine "geheime" URL enthält (manuell über die CLI oder die Weboberfläche - Oracle Cloud-Konsole generiert ). Tatsächlich reicht dies möglicherweise bereits für viele Szenarien aus, insbesondere wenn Sie Brute-Force-Dateinamen generieren, falls Sie diese nicht der Öffentlichkeit zugänglich machen möchten.
Ich war an der Möglichkeit interessiert, Dateien zu "teilen", dh öffentliche Links zu Dateien zu teilen und natürlich den Zugriff bei Bedarf einzuschränken. Mit einer kleinen Anzahl von Dateien können Sie dies manuell tun, aber wir sind hier versammelt, um programmgesteuerten Zugriff zu haben. AWS S3 nennt dies eine vorsignierte URL , während Oracle sie als vorauthentifizierte Anforderung bezeichnet .
Installieren des AWS PHP SDK
composer require aws/aws-sdk-php
Unten wird angezeigt, wo Sie Zugriff erhalten ( AWS_ACCESS_KEY_ID
und AWS_SECRET_ACCESS_KEY
.
Namespace kann gesehen werden
require('vendor/autoload.php');
$namespaceName = 'frpegp***';
$bucketName = 'test******05';
$region = 'eu-frankfurt-1';
$endpoint = "https://$namespaceName.compat.objectstorage.$region.oraclecloud.com";
$s3 = new Aws\S3\S3Client([
'version' => 'latest',
'region' => $region,
'endpoint' => $endpoint,
'signature_version' => 'v4',
'use_path_style_endpoint' => true,
'credentials' => [
'key' => 'AKI***YYJ', // remove if you have env var AWS_ACCESS_KEY_ID
'secret' => 'ndK***cIf', // remove if you have env var AWS_SECRET_ACCESS_KEY
],
]);
$cmd = $s3->getCommand('GetObject', [
'Bucket' => $bucketName,
'Key' => 'fff.txt'
]);
$request = $s3->createPresignedRequest($cmd, '+20 minutes');
var_dump($request);
object(GuzzleHttp\Psr7\Request)#146 (7) {
["method":"GuzzleHttp\Psr7\Request":private]=>
string(3) "GET"
["uri":"GuzzleHttp\Psr7\Request":private]=>
object(GuzzleHttp\Psr7\Uri)#148 (7) {
["scheme":"GuzzleHttp\Psr7\Uri":private]=>
string(5) "https"
...
["host":"GuzzleHttp\Psr7\Uri":private]=>
string(64) "{namespace}.compat.objectstorage.eu-frankfurt-1.oraclecloud.com"
...
["path":"GuzzleHttp\Psr7\Uri":private]=>
string(21) "/{bucket}/fff.txt"
["query":"GuzzleHttp\Psr7\Uri":private]=>
string(329) "X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=&&&%2F20210211%2Feu-frankfurt-1%2Fs3%2Faws4_request&X-Amz-Date=20210211T093350Z&X-Amz-SignedHeaders=host&X-Amz-Expires=1200&X-Amz-Signature=1e1b1***6ac992"
...
}
}
Diese Operation gibt als Antwort eine PSR-7-Anforderung zurück , aus der Sie eine URL des Formulars generieren können
https://{namespace}.compat.objectstorage.eu-frankfurt-1.oraclecloud.com/{bucket}/fff.txt?X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=***%2F20210210%2Feu-frankfurt-1%2Fs3%2Faws4_request&X-Amz-Date=20210210T185244Z&X-Amz-SignedHeaders=host&X-Amz-Expires=1200&X-Amz-Signature=a167a***9a857
Leider erlaubt dies jedoch keinen Widerruf des Zugriffs, beispielsweise wenn der Link "langwierig" ist.
, \\ , DNS Email. API Reference and Endpoints.
, , , , - () Oracle Cloud User Settings
API Keys — Add API Key
Download private key ( ), Add
,
, AWS PHP SDK, Customer Secret Keys ( AWS_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY
Amazon.
Oracle Cloud Infrastructure mini PHP SDK ( !)
composer require hitrov/oci-api-php-request-sign
PSR-4 .
require 'vendor/autoload.php';
use Hitrov\OCI\Signer;
( , , ).
OCI_TENANCY_ID=ocid1.tenancy.oc1..aaaaaaaaba3pv6wkcr4jqae5f15p2b2m2yt2j6rx32uzr4h25vqstifsfdsq OCI_USER_ID=ocid1.user.oc1..aaaaaaaat5nvwcna5j6aqzjcaty5eqbb6qt2jvpkanghtgdaqedqw3rynjq OCI_KEY_FINGERPRINT=20:3b:97:13:55:1c:5b:0d:d3:37:d8:50:4e:c5:3a:34 OCI_PRIVATE_KEY_FILENAME=/path/to/privatekey.pem
.
$signer = new Signer;
https://github.com/hitrov/oci-api-php-request-sign#alternatives-for-providing-credentials , .
CreatePreauthenticatedRequest.
( )
public function getHeaders(
string $url, string $method = 'GET', ?string $body = null, ?string $contentType = 'application/json', string $dateString = null
): array
$curl = curl_init();
$url = 'https://objectstorage.eu-frankfurt-1.oraclecloud.com/n/{namespaceName}/b/{bucketName}/p/';
$method = 'POST';
$body = '{"accessType": "ObjectRead", "name": "read-access-to-image.png", "objectName": "path/to/image.png", "timeExpires": "2021-03-01T00:00:00-00:00"}';
$headers = $signer->getHeaders($url, $method, $body, 'application/json');
var_dump($headers);
$curlOptions = [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 5,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => $method,
CURLOPT_HTTPHEADER => $headers,
];
if ($body) {
// not needed for GET or HEAD requests
$curlOptions[CURLOPT_POSTFIELDS] = $body;
}
curl_setopt_array($curl, $curlOptions);
$response = curl_exec($curl);
echo $response;
curl_close($curl);
array(6) {
[0]=>
string(35) "date: Mon, 08 Feb 2021 20:49:22 GMT"
[1]=>
string(50) "host: objectstorage.eu-frankfurt-1.oraclecloud.com"
[2]=>
string(18) "content-length: 76"
[3]=>
string(30) "content-type: application/json"
[4]=>
string(62) "x-content-sha256: X48E9qOokqqrvdts8nOJRJN3OWDUoyWxBf7kbu9DBPE="
[5]=>
string(538) "Authorization: Signature version=\"1\",keyId=\"ocid1.tenancy.oc1..aaaaaaaaba3pv6wkcr4jqae5f15p2b2m2yt2j6rx32uzr4h25vqstifsfdsq/ocid1.user.oc1..aaaaaaaat5nvwcna5j6aqzjcaty5eqbb6qt2jvpkanghtgdaqedqw3rynjq/20:3b:97:13:55:1c:5b:0d:d3:37:d8:50:4e:c5:3a:34\",algorithm=\"rsa-sha256\",headers=\"date (request-target) host content-length content-type x-content-sha256\",signature=\"LXWXDA8VmXXc1NRbMmXtW61IS97DfIOMAnlj+Gm+oBPNc2svXYdhcXNJ+oFPoi9qJHLnoUiHqotTzuVPXSG5iyXzFntvkAn3lFIAja52iwwwcJflEIXj/b39eG2dCsOTmmUJguut0FsLhCRSX0eylTSLgxTFGoQi7K/m18nafso=\""
}
{
"accessUri": "/p/AlIlOEsMok7oE7YkN30KJUDjDKQjk493BKbuM-ANUNGdBBAHzHT_5lFlzYC9CQiA/n/{namespaceName}/b/{bucketName}/o/path/to/image.png",
"id": "oHJQWGxpD+2PhDqtoewvLCf8/lYNlaIpbZHYx+mBryAad/q0LnFy37Me/quKhxEi:path/to/image.png",
"name": "read-access-to-image.png",
"accessType": "ObjectRead",
"objectName": "path/to/image.png",
"timeCreated": "2021-02-09T11:52:45.053Z",
"timeExpires": "2021-03-01T00:00:00Z"
}
!
, . , – .
1) , « » (SIGNING_HEADERS_NAMES).
date
· (request-target)
· host
POST|PUT|PATCH
· content-length
· content-type
· x-content-sha256
$signingHeadersNames = $signer->getSigningHeadersNames('POST');
2) SHA256 «» – base64
$bodyHashBase64 = $signer->getBodyHashBase64($body);
3) ,
date: Mon, 08 Feb 2021 20:51:33 GMT (request-target): post /n/{namespaceName}/b/{bucketName}/p/ host: objectstorage.eu-frankfurt-1.oraclecloud.com content-length: 76 content-type: application/json x-content-sha256: X48E9qOokqqrvdts8nOJRJN3OWDUoyWxBf7kbu9DBPE=
$signingString = $signer->getSigningString($url, $method, $body, 'application/json');
(2). , , 5 .
4) (3) RSA-SHA256
$signature = $signer->calculateSignature($signingString, $privateKeyString);
5) KEY_ID , API Key, ,
"{OCITENANCYID}/{OCIUSERID}/{OCIKEY_FINGERPRINT}"
$keyId = $signer->getKeyId();
6) ( 1
Oracle)
Authorization: Signature version=\"1\",keyId=\"{KEY_ID}\",algorithm=\"rsa-sha256\",headers=\"{SIGNING_HEADERS_NAMES_STRING}\",signature=\"{SIGNATURE}\"
SIGNING_HEADERS_NAMES_STRING – (1), .
date (request-target) host content-length content-type x-content-sha256
$signingHeadersNamesString = implode(' ', $signingHeadersNames);
$authorizationHeader = $signer->getAuthorizationHeader($keyId, $signingHeadersNamesString, $signature);
Authorization: Signature version=\"1\",keyId=\"ocid1.tenancy.oc1..aaaaaaaaba3pv6wkcr4jqae5f15p2b2m2yt2j6rx32uzr4h25vqstifsfdsq/ocid1.user.oc1..aaaaaaaat5nvwcna5j6aqzjcaty5eqbb6qt2jvpkanghtgdaqedqw3rynjq/20:3b:97:13:55:1c:5b:0d:d3:37:d8:50:4e:c5:3a:34\",algorithm=\"rsa-sha256\",headers=\"date (request-target) host content-length content-type x-content-sha256\",signature=\"LXWXDA8VmXXc1NRbMmXtW61IS97DfIOMAnlj+Gm+oBPNc2svXYdhcXNJ+oFPoi9qJHLnoUiHqotTzuVPXSG5iyXzFntvkAn3lFIAja52iwwwcJflEIXj/b39eG2dCsOTmmUJguut0FsLhCRSX0eylTSLgxTFGoQi7K/m18nafso=\"
- . var_dump()
- (3), (request-target) . , , (6).
Der REST-Aufruf für Oracle Cloud Infrastructure (OCI) mit Curl-Artikel hat mir geholfen . Einige der Methodennamen stammen aus dem offiziellen GoLang SDK . Testfälle - vom selben Ort .