config = get_addon_config('cos'); } public function getToken() { $config = $this->stsToken(); $uploadUrl = $this->config['uploadurl'];//上传域名因存储区域不同而节点不同 $cdnUrl = $this->config['cdnurl'];//上传域名因存储区域不同而节点不同 $appId = $this->config['appId'] ?? ''; $bucket = $this->config['bucket'] ?? '';//存储桶,格式:BucketName-APPID $region = $this->config['region'] ?? ''; $key = str_replace('-'.$appId,'',$bucket);//对象在存储桶中的位置,即对象键 $tmpSecretId = $config['credentials']['tmpSecretId']; //使用临时密钥需要填入,临时密钥生成和使用指引参见https://cloud.tencent.com/document/product/436/14048 $tmpSecretKey = $config['credentials']['tmpSecretKey']; //使用临时密钥需要填入,临时密钥生成和使用指引参见https://cloud.tencent.com/document/product/436/14048 $tmpToken = $config['credentials']['sessionToken']; //使用临时密钥需要填入,临时密钥生成和使用指引参见https://cloud.tencent.com/document/product/436/14048 $cosClient = new Client( array( 'region' => $region, 'scheme' => 'https', //协议头部,默认为 http 'signHost' => true, //默认签入Header Host;您也可以选择不签入Header Host,但可能导致请求失败或安全漏洞,若不签入host则填false 'credentials'=> array( 'secretId' => $tmpSecretId, 'secretKey' => $tmpSecretKey, 'token' => $tmpToken))); ### 简单上传预签名 try { $signedUrl = $cosClient->getPreSignedUrl('putObject', array( 'Bucket' => $bucket, //存储桶,格式:BucketName-APPID 'Key' => $key, //对象在存储桶中的位置,即对象键 'Body' => 'string', 'Params'=> array(), //http 请求参数,传入的请求参数需与实际请求相同,能够防止用户篡改此HTTP请求的参数,默认为空 'Headers'=> array(), //http 请求头部,传入的请求头部需包含在实际请求中,能够防止用户篡改签入此处的HTTP请求头部,默认已签入host ), '+10 minutes'); //签名的有效时间 // 请求成功 // 请求成功 return [true,[ 'bucket' => $bucket, 'region' => $region, 'uploadUrl' => $uploadUrl, 'cdnUrl' => $cdnUrl, 'signUrl' => $signedUrl, ]]; } catch (\Exception $e) { // 请求失败 return [false,$e->getMessage()]; } } /** * 腾讯云预签名URL */ public function getSignedUrl($dir = 'uploads/') { $uploadUrl = $this->config['uploadurl'];//上传域名因存储区域不同而节点不同 $cdnUrl = $this->config['cdnurl'];//上传域名因存储区域不同而节点不同 $secretId = $this->config['secretId'] ?? ''; $secretKey = $this->config['secretKey'] ?? ''; $bucket = $this->config['bucket'] ?? ''; $region = $this->config['region'] ?? ''; $time = time(); // $cosClient = new Client([ // 'region' => $region, // 'schema' => $ssl, //协议头部,默认为http // 'signHost' => true, //默认签入Header Host;您也可以选择不签入Header Host,但可能导致请求失败或安全漏洞,若不签入host则填false // 'credentials' => [ // 'secretId' => $secretId, // 'secretKey' => $secretKey // ] // ]); try { // $signedUrl = $cosClient->getPreSignedUrl('putObject', [ // 'Bucket' => $bucket, //存储桶,格式:BucketName-APPID // 'Key' => $dir, //对象在存储桶中的位置,即对象键 // 'Body' => 'string', // 'Params' => [], //http 请求参数,传入的请求参数需与实际请求相同,能够防止用户篡改此HTTP请求的参数,默认为空 // 'Headers' => [], //http 请求头部,传入的请求头部需包含在实际请求中,能够防止用户篡改签入此处的HTTP请求头部,默认已签入host // ], '+10 minutes'); //签名的有效时间 //设置该policy超时时间是10s. 即这个policy过了这个有效时间,将不能访问。 $addTime = 30 * 60;//三十分钟 $expiration = $this->gmt_iso8601($time + $addTime); $StartTimestamp = $time; $EndTimestamp = $StartTimestamp + $addTime; $KeyTime = "$StartTimestamp;$EndTimestamp"; $conditions = [ ['content-length-range', 0, 1048576000],//最大文件大小.用户可以自己设置 ["bucket" => $bucket], ["starts-with", '$key', $dir],// 表示用户上传的数据,必须是以$dir开始,不然上传会失败,这一步不是必须项,只是为了安全起见,防止用户通过policy上传到别人的目录。 ["q-sign-algorithm" => "sha1"], ["q-ak" => $secretId], ["q-sign-time" => $KeyTime] ]; $arr = ['expiration' => $expiration, 'conditions' => $conditions]; $policy = json_encode($arr); $policyBase64 = base64_encode($policy); // 签名 $SignKey = hash_hmac('sha1', $KeyTime, $secretKey); $StringToSign = sha1($policy); $Signature = hash_hmac('sha1', $StringToSign, $SignKey); // 请求成功 return [true, [ 'upload_url' => $uploadUrl, 'cdn_url' => $cdnUrl, 'region' => $region, 'policy' => $policyBase64, 'q_sign_algorithm' => 'sha1', 'q_ak' => $secretId, 'q_key_time' => $KeyTime, 'q_signature' => $Signature, ]]; } catch (\Exception $e) { return [false, $e->getMessage()]; } } public function stsToken() { $uploadUrl = $this->config['uploadurl'];//上传域名因存储区域不同而节点不同 $cdnUrl = $this->config['cdnurl'];//上传域名因存储区域不同而节点不同 $secretId = $this->config['secretId'] ?? ''; $secretKey = $this->config['secretKey'] ?? ''; $bucket = $this->config['bucket'] ?? ''; $region = $this->config['region'] ?? ''; $sts = new Sts(); $config = array( 'url' => 'https://sts.tencentcloudapi.com/', // url和domain保持一致 'domain' => 'sts.tencentcloudapi.com', // 域名,非必须,默认为 sts.tencentcloudapi.com 'proxy' => '', 'secretId' => $secretId, // 固定密钥,若为明文密钥,请直接以'xxx'形式填入,不要填写到getenv()函数中 'secretKey' => $secretKey, // 固定密钥,若为明文密钥,请直接以'xxx'形式填入,不要填写到getenv()函数中 'bucket' => $bucket,//'test-1253653367', // 换成你的 bucket 'region' => $region,//'ap-guangzhou', // 换成 bucket 所在园区 'durationSeconds' => 1800, // 密钥有效期 'allowPrefix' => array('exampleobject.jpg','exampleobject.png','exampleobject/*'), // 这里改成允许的路径前缀,可以根据自己网站的用户登录态判断允许上传的具体路径,例子: a.jpg 或者 a/* 或者 * (使用通配符*存在重大安全风险, 请谨慎评估使用) // 密钥的权限列表。简单上传和分片需要以下的权限,其他权限列表请看 https://cloud.tencent.com/document/product/436/31923 'allowActions' => array ( // 简单上传 'name/cos:PutObject', 'name/cos:PostObject', // 分片上传 'name/cos:InitiateMultipartUpload', 'name/cos:ListMultipartUploads', 'name/cos:ListParts', 'name/cos:UploadPart', 'name/cos:CompleteMultipartUpload' ), // 临时密钥生效条件,关于condition的详细设置规则和COS支持的condition类型可以参考 https://cloud.tencent.com/document/product/436/71306 // "condition" => array( // "ip_equal" => array( // "qcs:ip" => array( // "10.217.182.3/24", // "111.21.33.72/24", // ) // ) // ) ); // 获取临时密钥,计算签名 $tempKeys = $sts->getTempKeys($config); return $tempKeys; } private function xml_parser($str) { $xml_parser = xml_parser_create(); if (!xml_parse($xml_parser, $str, true)) { xml_parser_free($xml_parser); return $str; } else { $res = json_decode(json_encode(simplexml_load_string($str, 'SimpleXMLElement', LIBXML_NOCDATA)), true); return $res['Message'] ?? '请求错误'; } } /** * @param $time * @return string * @throws \Exception */ private function gmt_iso8601($time) { $dtStr = date("c", $time); $dateTime = new \DateTime($dtStr); $expiration = $dateTime->format(\DateTime::ISO8601); $pos = strpos($expiration, '+'); $expiration = substr($expiration, 0, $pos); return $expiration . "Z"; } }