| /** * OSS超直传签名 * @return array * @author: luwc * @Time: 2021/12/11 10:56 */ public function actionOssSign() { $oss = \Yii::$app->params['oss']; $dir = 'userprefix/' . date('Ymd') . '/'; // 用户上传文件时指定的前缀。 $callbackUrl = \Yii::$app->request->hostInfo . '/api/index/oss-call-back'; $base64_callback_body = base64_encode(json_encode([ 'callbackUrl' => $callbackUrl, 'callbackBody' => 'filename=${object}&size=${size}&mimeType=${mimeType}&height=${imageInfo.height}&width=${imageInfo.width}', 'callbackBodyType' => "application/x-www-form-urlencoded" ])); $now = time(); $expire = 30; //设置该policy超时时间是10s. 即这个policy过了这个有效时间,将不能访问。 $end = $now + $expire; $expiration = str_replace('+00:00', '.000Z', gmdate('c', $end)); $conditions = [ //最大文件大小.用户可以自己设置 [0 => 'content-length-range', 1 => 0, 2 => 1048576000], // 表示用户上传的数据,必须是以$dir开始,不然上传会失败,这一步不是必须项,只是为了安全起见,防止用户通过policy上传到别人的目录。 [0 => 'starts-with', 1 => '$key', 2 => $dir] ]; $base64_policy = base64_encode(json_encode( ['expiration' => $expiration, 'conditions' => $conditions] )); $string_to_sign = $base64_policy; $signature = base64_encode(hash_hmac('sha1', $string_to_sign, $oss['accessKeySecret'], true)); $response = []; $response['accessid'] = $oss['accessKeyId']; $response['host'] = 'http://' .$oss['bucket'].'.'. $oss['endPoint']; $response['policy'] = $base64_policy; $response['signature'] = $signature; $response['expire'] = $end; $response['callback'] = $base64_callback_body; $response['dir'] = $dir; // 这个参数是设置用户上传文件时指定的前缀。 return $this->success($response); } /** * OSS超直传回调 * @author: luwc * @Time: 2021/12/11 11:04 */ public function actionOssCallBack() { // 1.获取OSS的签名header和公钥url header $authorizationBase64 = ""; $pubKeyUrlBase64 = ""; /* * 注意:如果要使用HTTP_AUTHORIZATION头,你需要先在apache或者nginx中设置rewrite,以apache为例,修改 * 配置文件/etc/httpd/conf/httpd.conf(以你的apache安装路径为准),在DirectoryIndex index.php这行下面增加以下两行 RewriteEngine On RewriteRule .* - [env=HTTP_AUTHORIZATION:%{HTTP:Authorization},last] * */ if (isset($_SERVER['HTTP_AUTHORIZATION'])) { $authorizationBase64 = $_SERVER['HTTP_AUTHORIZATION']; } if (isset($_SERVER['HTTP_X_OSS_PUB_KEY_URL'])) { $pubKeyUrlBase64 = $_SERVER['HTTP_X_OSS_PUB_KEY_URL']; } \Yii::info(print_r([$authorizationBase64, $pubKeyUrlBase64], 'OSS超直传回调')); if ($authorizationBase64 == '' || $pubKeyUrlBase64 == '') { return $this->error([],'授权参数错误'); } // 2.获取OSS的签名 $authorization = base64_decode($authorizationBase64); // 3.获取公钥 $pubKeyUrl = base64_decode($pubKeyUrlBase64); \Yii::info(print_r([$pubKeyUrl], 'OSS超直传回调')); $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $pubKeyUrl); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10); $pubKey = curl_exec($ch); \Yii::info(print_r([$pubKey], 'OSS超直传回调')); if ($pubKey == "") { // header("http/1.1 403 Forbidden"); return $this->error([],'获取公钥失败'); } // 4.获取回调body $body = file_get_contents('php://input'); // 5.拼接待签名字符串 $authStr = ''; $path = $_SERVER['REQUEST_URI']; $pos = strpos($path, '?'); if ($pos === false) { $authStr = urldecode($path) . "\n" . $body; } else { $authStr = urldecode(substr($path, 0, $pos)) . substr($path, $pos, strlen($path) - $pos) . "\n" . $body; } // 6.验证签名 $ok = openssl_verify($authStr, $authorization, $pubKey, OPENSSL_ALGO_MD5); if ($ok == 1) { $oss = \Yii::$app->params['oss']; $arrBody = []; parse_str(urldecode($body), $arrBody); $ossUrl = $oss['domain'] . '/' . $arrBody['filename']; \Yii::info(print_r([$arrBody, $body], true), 'OSS超直传回调'); // 入库 ImageType::insertData(['info_type' => 0, 'info_id' => 0, 'key' => $arrBody['filename'], 'oss_path' => $ossUrl]); return $this->success(['url' => $ossUrl]); } else { // header("http/1.1 403 Forbidden"); return $this->error([], '验证签名失败'); } } |