/** * 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([], '验证签名失败' ); } } |