filesystem 扩展支持 s3 作为驱动上传文件, 然后aws s3 扩展php8 就不支持v2 签名了,想要使用v2 兼容性加密,需要通过配置里provide 的方法来。
's3' => [
'driver' => 's3',
'root' => 'storage',
'key' => env('AWS_ACCESS_KEY_ID'),
'secret' => env('AWS_SECRET_ACCESS_KEY'),
'region' => env('AWS_DEFAULT_REGION'),
'bucket' => env('AWS_BUCKET'),
'url' => env('AWS_URL'),
'endpoint' => env('AWS_ENDPOINT'),
'use_path_style_endpoint' => env('AWS_USE_PATH_STYLE_ENDPOINT', false),
'throw' => true,
'visibility' => 'public',
'signature_version'=>'v2',
// 'debug'=>true,
'http'=>[
// 'debug'=>true,
'verify'=>false,
],
'signature_provider'=>function($version, $service, $region) {
switch ($version) {
case 's3v4':
case 'v2':
case 's3':
return new S3Signature();
default:
return null;
}
},
],
// 下面是上面配置文件用到的类 S3Signature 放入 extend 目录 即可。记得composer 装 league/flysystem-aws-s3-v3 这个包
<?php/** * @copyright Copyright (c) 2016 Robin Appelman <robin@icewind.nl> * * @author Christoph Wurst <christoph@winzerhof-wurst.at> * @author Daniel Kesselberg <mail@danielkesselberg.de> * @author Robin Appelman <robin@icewind.nl> * * @license GNU AGPL version 3 or any later version * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * */namespaceSignature;
useAws\Credentials\CredentialsInterface;
useAws\S3\S3Client;
useAws\S3\S3UriParser;
useAws\Signature\SignatureInterface;
useGuzzleHttp\Psr7;
usePsr\Http\Message\RequestInterface;
/** * Legacy Amazon S3 signature implementation */class S3Signature implements SignatureInterface {
/** @var array Query string values that must be signed */private$signableQueryString = [
'acl', 'cors', 'delete', 'lifecycle', 'location', 'logging',
'notification', 'partNumber', 'policy', 'requestPayment',
'response-cache-control', 'response-content-disposition',
'response-content-encoding', 'response-content-language',
'response-content-type', 'response-expires', 'restore', 'tagging',
'torrent', 'uploadId', 'uploads', 'versionId', 'versioning',
'versions', 'website'
];
/** @var array Sorted headers that must be signed */private$signableHeaders = ['Content-MD5', 'Content-Type'];
/** @var \Aws\S3\S3UriParser S3 URI parser */private$parser;
publicfunction__construct() {
$this->parser = newS3UriParser();
// Ensure that the signable query string parameters are sortedsort($this->signableQueryString);
}
publicfunctionsignRequest(
RequestInterface$request,
CredentialsInterface$credentials
) {
$request = $this->prepareRequest($request, $credentials);
$stringToSign = $this->createCanonicalizedString($request);
$auth = 'AWS '
. $credentials->getAccessKeyId() . ':'
. $this->signString($stringToSign, $credentials);
return$request->withHeader('Authorization', $auth);
}
publicfunctionpresign(
RequestInterface$request,
CredentialsInterface$credentials,
$expires,
array$options = []
) {
$query = [];
// URL encoding already occurs in the URI template expansion. Undo that// and encode using the same encoding as GET object, PUT object, etc.$uri = $request->getUri();
$path = S3Client::encodeKey(rawurldecode($uri->getPath()));
$request = $request->withUri($uri->withPath($path));
// Make sure to handle temporary credentialsif ($token = $credentials->getSecurityToken()) {
$request = $request->withHeader('X-Amz-Security-Token', $token);
$query['X-Amz-Security-Token'] = $token;
}
if ($expiresinstanceof \DateTime) {
$expires = $expires->getTimestamp();
} elseif (!is_numeric($expires)) {
$expires = strtotime($expires);
}
// Set query params required for pre-signed URLs$query['AWSAccessKeyId'] = $credentials->getAccessKeyId();
$query['Expires'] = $expires;
$query['Signature'] = $this->signString(
$this->createCanonicalizedString($request, $expires),
$credentials
);
// Move X-Amz-* headers to the query stringforeach ($request->getHeaders() as$name => $header) {
$name = strtolower($name);
if (strpos($name, 'x-amz-') === 0) {
$query[$name] = implode(',', $header);
}
}
$queryString = http_build_query($query, null, '&', PHP_QUERY_RFC3986);
return$request->withUri($request->getUri()->withQuery($queryString));
}
/** * @param RequestInterface $request * @param CredentialsInterface $creds * * @return RequestInterface */privatefunctionprepareRequest(
RequestInterface$request,
CredentialsInterface$creds
) {
$modify = [
'remove_headers' => ['X-Amz-Date'],
'set_headers' => ['Date' => gmdate(\DateTimeInterface::RFC2822)]
];
// Add the security token header if one is being used by the credentialsif ($token = $creds->getSecurityToken()) {
$modify['set_headers']['X-Amz-Security-Token'] = $token;
}
returnPsr7\Utils::modifyRequest($request, $modify);
}
privatefunctionsignString($string, CredentialsInterface$credentials) {
returnbase64_encode(
hash_hmac('sha1', $string, $credentials->getSecretKey(), true)
);
}
privatefunctioncreateCanonicalizedString(
RequestInterface$request,
$expires = null
) {
$buffer = $request->getMethod() . "\n";
// Add the interesting headersforeach ($this->signableHeadersas$header) {
$buffer .= $request->getHeaderLine($header) . "\n";
}
$date = $expires ?: $request->getHeaderLine('date');
$buffer .= "{$date}\n"
. $this->createCanonicalizedAmzHeaders($request)
. $this->createCanonicalizedResource($request);
return$buffer;
}
privatefunctioncreateCanonicalizedAmzHeaders(RequestInterface$request) {
$headers = [];
foreach ($request->getHeaders() as$name => $header) {
$name = strtolower($name);
if (strpos($name, 'x-amz-') === 0) {
$value = implode(',', $header);
if (strlen($value) > 0) {
$headers[$name] = $name . ':' . $value;
}
}
}
if (!$headers) {
return'';
}
ksort($headers);
returnimplode("\n", $headers) . "\n";
}
privatefunctioncreateCanonicalizedResource(RequestInterface$request) {
$data = $this->parser->parse($request->getUri());
$buffer = '/';
if ($data['bucket']) {
$buffer .= $data['bucket'];
if (!empty($data['key']) || !$data['path_style']) {
$buffer .= '/' . $data['key'];
}
}
// Add sub resource parameters if present.$query = $request->getUri()->getQuery();
if ($query) {
$params = Psr7\Query::parse($query);
$first = true;
foreach ($this->signableQueryStringas$key) {
if (array_key_exists($key, $params)) {
$value = $params[$key];
$buffer .= $first ? '?' : '&';
$first = false;
$buffer .= $key;
// Don't add values for empty sub-resourcesif (strlen($value)) {
$buffer .= "={$value}";
}
}
}
}
return$buffer;
}
}
杨维杰
4 个月前
⚙️这个扩展很奈斯
filesystem 扩展支持 s3 作为驱动上传文件, 然后aws s3 扩展php8 就不支持v2 签名了,想要使用v2 兼容性加密,需要通过配置里provide 的方法来。
以上代码在天翼云存储可以使用,缺点,路由缓存生成会报错