首先使用阿里雲函數計算進行簽名,避免Aliyun AccessId/AccessKey 暴露在外面,造成安全風險。
使用者上傳文件的邏輯是:
1. 先獲取上傳oss的 policy 及簽名
2. 然后根據拿到簽名直接上傳到aliyun OSS
阿里雲簽名代碼:
1 <?php 2 use RingCentral\Psr7\Response; 3 4 function gmt_iso8601($time) { 5 $dtStr = date("c", $time); 6 $mydatetime = new DateTime($dtStr); 7 $expiration = $mydatetime->format(DateTime::ISO8601); 8 $pos = strpos($expiration, '+'); 9 $expiration = substr($expiration, 0, $pos); 10 return $expiration."Z"; 11 } 12 13 function oss_fun($auth){ 14 /* 15 這里是鑒權,校驗失敗直接返回401,不做分享 16 return json_encode(['status'=>401]); 17 */ 18 //阿里雲官方提供的秘鑰 19 $id= 'aliyun accessid'; 20 $key= 'aliyun accesskey'; 21 $host = 'http://oss-host.domain.com'; 22 //$host = 'https://oss-host.oss-cn-hangzhou.aliyuncs.com'; 23 $rand_str = rand_str(); 24 25 $dir = 'public-dir-7day-delete/'.date("Ymd-His",time()).'_'.$rand_str.'/'; 26 27 $now = time(); 28 $expire = 180; //設置該policy超時時間是180s. 即這個policy過了這個有效時間,將不能訪問 29 $end = $now + $expire; 30 $expiration = gmt_iso8601($end); 31 32 //最大文件大小.當前50MB與web頁面相同 33 $condition = array(0=>'content-length-range', 1=>0, 2=>1024*1024*50); 34 $conditions[] = $condition; 35 36 //表示用戶上傳的數據,必須是以$dir開始, 不然上傳會失敗,這一步不是必須項,只是為了安全起見,防止用戶通過policy上傳到別人的目錄 37 $start = array(0=>'starts-with', 1=>'$key', 2=>$dir); 38 $conditions[] = $start; 39 40 $arr = array('expiration'=>$expiration,'conditions'=>$conditions); 41 $policy = json_encode($arr); 42 $base64_policy = base64_encode($policy); 43 $string_to_sign = $base64_policy; 44 $signature = base64_encode(hash_hmac('sha1', $string_to_sign, $key, true)); 45 46 $response = array(); 47 $response['accessid'] = $id; 48 $response['host'] = $host; 49 $response['policy'] = $base64_policy; 50 $response['signature'] = $signature; 51 $response['expire'] = $end; 52 //這個參數是設置用戶上傳指定的前綴 53 $response['dir'] = $dir; 54 $response['id'] = $rand_str; 55 56 return json_encode(['status'=>200,'data'=>$response]); 57 } 58 59 60 function rand_str( $length = 32 ){ 61 $str='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890'; 62 $randStr = str_shuffle($str);//打亂字符串 63 $rands= substr($randStr,0,$length);//substr(string,start,length);返回字符串的一部分 64 return $rands; 65 } 66 function handler($request, $context): Response{ 67 68 $body = $request->getBody()->getContents(); 69 $queries = $request->getQueryParams(); 70 $method = $request->getMethod(); 71 $headers = $request->getHeaders(); 72 $path = $request->getAttribute('path'); 73 $requestURI = $request->getAttribute('requestURI'); 74 $clientIP = $request->getAttribute('clientIP'); 75 76 $auth = isset($headers['Authorization']) ? $headers['Authorization'][0]:null; 77 return new Response( 78 200, 79 array( 80 'Content-Type' => 'application/json; charset=utf-8', 81 ), 82 oss_fun($auth) 83 ); 84 }
編寫 shell ,用於快速上傳到阿里雲oss平台:
1 #!/bin/bash 2 3 # jq -h >/dev/null 2>&1 ; if [ $? -ne 0 ]; then echo "Need jq";exit; fi 4 jq -h >/dev/null 2>&1 || { echo "Need jq";exit; } 5 6 function upload_file(){ 7 8 #oss=$(curl -s http://root:password@fc.domain.com/upload2oss)#鑒權 9 oss=$(curl -s http://fc.domain.com/upload2oss) #獲取簽名的json 10 #echo $oss | python -m json.tool 11 startTime_s=`date +%s.%N` 12 dir=`echo $oss | jq .data.dir | sed \s/\"//g` 13 host=`echo $oss | jq .data.host | sed \s/\"//g` 14 policy=`echo $oss | jq .data.policy | sed \s/\"//g` 15 accessid=`echo $oss | jq .data.accessid | sed \s/\"//g` 16 signature=`echo $oss | jq .data.signature | sed \s/\"//g` 17 18 curl -XPOST -sk ${host} \ 19 -F "policy=${policy}" \ 20 -F "Signature=${signature}" \ 21 -F "success_action_status=200" \ 22 -F "OSSAccessKeyId=${accessid}" \ 23 -F "x-oss-object-acl=public-read" \ 24 -F "key=${dir}${1}" \ 25 -F "file=@${2}" 26 27 endTime_s=`date +%s.%N` 28 runTime=`echo $endTime_s $startTime_s | awk '{print $1-$2}'` 29 status=`curl -sI "${host}/${dir}${1}" | awk 'NR==1{print $2}'` 30 31 if [ "${status}"x == "200"x ]; then 32 echo -e "${2} \t ${host}/${dir}${1} \t ${runTime}s" 33 else 34 echo "Upload failed: ${status}" 35 fi 36 } 37 38 for i in $*; do 39 if [ ! -f ${i} ]; then 40 echo "${i} no file"; continue; 41 else 42 upload_file ${i##*/} ${i} 43 fi 44 done
效果如下:
1 [litry@HK ~]# ./oss.sh oss.sh docker.sh 2 oss.sh http://oss-host.domain.com/public-dir-7day-delete/20201009-150007_lQGImxc7dtrkXqCh/oss.sh 1.91704s 3 docker.sh http://oss-host.domain.com/public-dir-7day-delete/20201009-150009_QBg0W5JFbelL26GN/docker.sh 0.498585s 4 [litry@HK ~]#
