PHP项目直传签名如何生成临时凭证

wen PHP项目 27

本文目录导读:

PHP项目直传签名如何生成临时凭证

  1. 阿里云OSS 直传签名
  2. 腾讯云COS 直传签名
  3. AWS S3 直传签名
  4. 通用直传签名(自建服务)
  5. 最佳实践建议

在PHP项目中生成临时凭证(直传签名),通常用于阿里云OSS、腾讯云COS或AWS S3等云存储服务的客户端直传场景,以下是几种常见云服务的实现方式:

阿里云OSS 直传签名

使用STS临时凭证(推荐)

<?php
use OSS\OssClient;
use OSS\Core\OssException;
require_once 'vendor/autoload.php';
// 配置
$accessKeyId = 'your-access-key-id';
$accessKeySecret = 'your-access-key-secret';
$roleArn = 'acs:ram::123456789:role/oss-upload-role'; // RAM角色ARN
$bucket = 'your-bucket';
$region = 'oss-cn-hangzhou';
try {
    $ossClient = new OssClient($accessKeyId, $accessKeySecret, "https://sts.{$region}.aliyuncs.com");
    // 申请临时凭证
    $response = $ossClient->assumeRole($roleArn, 'session-name-'.time(), 3600);
    $tempCredentials = [
        'accessKeyId' => $response['Credentials']['AccessKeyId'],
        'accessKeySecret' => $response['Credentials']['AccessKeySecret'],
        'securityToken' => $response['Credentials']['SecurityToken'],
        'expiration' => $response['Credentials']['Expiration'],
        'region' => $region,
        'bucket' => $bucket
    ];
    echo json_encode($tempCredentials);
} catch (OssException $e) {
    echo json_encode(['error' => $e->getMessage()]);
}

简单上传签名(不使用STS)

<?php
function getOssUploadSignature($bucket, $object, $expiration = 3600) {
    $accessKeyId = 'your-access-key-id';
    $accessKeySecret = 'your-access-key-secret';
    $region = 'oss-cn-hangzhou';
    $host = "{$bucket}.{$region}.aliyuncs.com";
    $expireTime = time() + $expiration;
    $expirationGmt = gmdate('Y-m-d\TH:i:s\Z', $expireTime);
    $policy = [
        'expiration' => $expirationGmt,
        'conditions' => [
            ['bucket' => $bucket],
            ['eq', '$key', $object],
            ['content-length-range', 0, 1048576000]
        ]
    ];
    $policyJson = json_encode($policy);
    $policyBase64 = base64_encode($policyJson);
    $signature = base64_encode(hash_hmac('sha1', $policyBase64, $accessKeySecret, true));
    return [
        'accessid' => $accessKeyId,
        'host' => "https://{$host}",
        'policy' => $policyBase64,
        'signature' => $signature,
        'expire' => $expireTime,
        'key' => $object,
        'callback' => '' // 可选:回调URL
    ];
}

腾讯云COS 直传签名

使用临时密钥(推荐)

<?php
require_once 'vendor/autoload.php';
use Qcloud\Cos\Client;
$secretId = 'your-secret-id';
$secretKey = 'your-secret-key';
$region = 'ap-guangzhou';
$bucket = 'example-1250000000';
// 获取临时密钥
try {
    $cosClient = new Client([
        'region' => $region,
        'schema' => 'https',
        'credentials' => [
            'secretId' => $secretId,
            'secretKey' => $secretKey
        ]
    ]);
    // 申请临时密钥(需额外安装Qcloud/Cos模块)
    $result = $cosClient->getObjectUrl($bucket, 'test.txt', '+1 hour');
    // 或者手动生成临时密钥
    $tempKeys = [
        'TmpSecretId' => 'your-temp-secret-id',
        'TmpSecretKey' => 'your-temp-secret-key',
        'Token' => 'your-temp-token',
        'ExpiredTime' => time() + 3600,
        'StartTime' => time(),
        'Region' => $region,
        'Bucket' => $bucket
    ];
    echo json_encode($tempKeys);
} catch (Exception $e) {
    echo json_encode(['error' => $e->getMessage()]);
}

简单上传签名

<?php
function getCosUploadSignature($bucket, $region, $expiration = 3600) {
    $secretId = 'your-secret-id';
    $secretKey = 'your-secret-key';
    $currentTime = time();
    $keyTime = "{$currentTime};{$currentTime}+{$expiration}";
    $signKey = hash_hmac('sha1', $keyTime, $secretKey);
    // 构建签名
    $httpMethod = 'post';
    $uri = '/';
    $headers = "host={$bucket}.cos.{$region}.myqcloud.com";
    $params = '';
    $stringToSign = "{$httpMethod}\n{$uri}\n{$params}\n{$headers}\n";
    $signature = hash_hmac('sha1', $stringToSign, $signKey);
    return [
        'secretId' => $secretId,
        'signature' => $signature,
        'keyTime' => $keyTime,
        'bucket' => $bucket,
        'region' => $region
    ];
}

AWS S3 直传签名

<?php
require 'vendor/autoload.php';
use Aws\S3\S3Client;
use Aws\Credentials\Credentials;
// 配置
$region = 'us-east-1';
$bucket = 'your-bucket';
$awsKey = 'your-aws-access-key';
$awsSecret = 'your-aws-secret-key';
// 创建S3客户端
$s3Client = new S3Client([
    'version' => 'latest',
    'region' => $region,
    'credentials' => new Credentials($awsKey, $awsSecret)
]);
// 生成预签名上传URL
try {
    $command = $s3Client->getCommand('PutObject', [
        'Bucket' => $bucket,
        'Key' => 'uploads/' . uniqid() . '.jpg',
        'ACL' => 'public-read',
        'ContentType' => 'image/jpeg'
    ]);
    $presignedUrl = $s3Client->createPresignedRequest($command, '+1 hour');
    $url = (string) $presignedUrl->getUri();
    echo json_encode(['uploadUrl' => $url]);
} catch (Exception $e) {
    echo json_encode(['error' => $e->getMessage()]);
}

通用直传签名(自建服务)

<?php
class DirectUploadSigner {
    private $secretKey;
    public function __construct($secretKey) {
        $this->secretKey = $secretKey;
    }
    public function generateSignedUrl($bucket, $object, $expiration = 3600) {
        $expireTime = time() + $expiration;
        $data = "{$bucket}|{$object}|{$expireTime}";
        $signature = hash_hmac('sha256', $data, $this->secretKey);
        return [
            'url' => "https://your-storage.com/{$bucket}/{$object}",
            'expires' => $expireTime,
            'signature' => $signature,
            'key' => $object,
            'token' => base64_encode("{$signature}:{$expireTime}:{$bucket}:{$object}")
        ];
    }
    public function verifySignedToken($token) {
        $decoded = base64_decode($token);
        $parts = explode(':', $decoded);
        if (count($parts) !== 4) {
            return false;
        }
        list($signature, $expireTime, $bucket, $object) = $parts;
        // 检查是否过期
        if (time() > $expireTime) {
            return false;
        }
        // 验证签名
        $data = "{$bucket}|{$object}|{$expireTime}";
        $expectedSignature = hash_hmac('sha256', $data, $this->secretKey);
        return hash_equals($expectedSignature, $signature);
    }
}
// 使用示例
$signer = new DirectUploadSigner('your-secret-key-here');
$signedData = $signer->generateSignedUrl('my-bucket', 'photos/avatar.jpg', 3600);
echo json_encode($signedData);

最佳实践建议

  1. 安全考虑

    • 永远不要在客户端暴露长期密钥
    • 使用STS/RAM角色获取临时凭证
    • 设置合理的过期时间(通常15分钟-1小时)
    • 限制上传文件类型和大小
  2. 性能优化

    • 缓存临时凭证到会话或内存
    • 预生成多个签名减少请求
  3. 错误处理

    • 添加重试机制
    • 完善的日志记录
    • 前端签名验证
  4. 权限控制

    • 最小权限原则
    • 每个用户/请求独立签名
    • 后端验证上传完成的文件

选择哪种方案取决于你的云服务提供商和具体需求,推荐使用云服务商的STS临时凭证方案,安全性更高。

抱歉,评论功能暂时关闭!