首先使用阿里云函数计算进行签名,避免Aliyun AccessId/AccessKey 暴露在外面,造成安全风险。
使用者上传文件的逻辑是:
1. 先获取上传oss的 policy 及签名
2. 然后根据拿到签名直接上传到aliyun OSS
阿里云签名代码:
1 <?php 2 use RingCentralPsr7Response; 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} ${host}/${dir}${1} ${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 ~]#