<?php
/**
* 公共方法
*/
defined('DYMall') or exit('Access Invalid!');
use OSSOssClient;
use OSSCoreOssUtil;
use OSSCoreOssException;
use OSSHttpRequestCore;
use OSSHttpResponseCore;
require_once(BASE_ROOT_PATH.'/library/smartphp/libraries/OSS/autoload.php');
class osssecurityCtl{
const OSS_URL_KEY = 'ossSecurityUrl';
const OSS_TIME = 3600;
const OSS_STS_URL = 'https://sts.aliyuncs.com';
const FORMAT = 'JSON';
const VERSION = '2015-04-01';
const SIGN_ATURE_METHOD = 'HMAC-SHA1';
const SIGN_ATURE_VERSION = '1.0';
const ROLE_SESSION_NAME = 'web****ss';
const OSS_STS_TOKEN = 'images:oss:sts:token';
const OSS_ARN = 'acs:ram::136*******:role/w*****s'; //格式说明oss官网上有说明
const OSS_STS_ACCESS_ID = 'LTAI4****9u3h';
const OSS_ACCESE_SECRET = 'bv*******3B';
/**
* The name and signature of the console command.
* @var string
*/
protected $signature = 'get:OssStsToken';
/**
* The console command description.
*
* @var string
*/
protected $description = '[OSS]定期更新OSS Sts Token';
public function __construct()
{
$this->redis = caching::getInstance();
}
public function index(){
//生成token
$token = $this->handle();
$endpoint = $GLOBALS['setting_config']['oss_url'];
$bucket = $GLOBALS['setting_config']['oss_pre'];
$object = 'data/upload/mobile/share/poster/'; //oss的图片上传路径,后面必须加上反斜杠否则报错
//此处有个坑,阿里云文档中没有写明,此处因为是生成临时鉴权,来传递图片,所以用建立用户时生成的acesseckeyid去生成token,
// 生成的$token 会返回临时的 token值跟 AccessKeyId 跟 AccessKeySecret 跟Expiration 此处是生成的临时用的 acessid 跟 accesesecret
// 然后用生成的临时的 acceesskeyid 跟 accesskeysecret 跟token去生成临时鉴权的url ,不要用原来的 OSS_STS_ACCESS_ID
$ossClient = new OSSOssClient($token['AccessKeyId'], $token['AccessKeySecret'], $endpoint, false, $token['SecurityToken']);
try{
$is_keys = $this->redis->exists(self::OSS_URL_KEY);
if($is_keys) {
$signedUrl = $this->redis->get(self::OSS_URL_KEY);
}else{
// 生成PutObject的签名URL。
$signedUrl = $ossClient->signUrl($bucket, $object, self::OSS_TIME);
$this->redis->set(self::OSS_URL_KEY, $signedUrl, self::OSS_TIME);
}
}catch (OssException $e){
output_error($e->getMessage());
}
$signedUrl = $signedUrl.'&AccessKeySecret='.$token['AccessKeySecret'].'&bucketName='.$bucket.'&endpoint='.$endpoint;
$arr = parse_url($signedUrl);
$arrQeury = $arr['query'];
$explarr = explode('&', $arrQeury);
$urlarr = [];
foreach($explarr as $k =>$v){
$arr1=explode('=',$v);
$urlarr[$arr1[0]] = $arr1[1];
}
output_data($urlarr);//此处是将数据json后返回前段,token会被转义,所以前段拿到值后需要jsondecode一下在转义回来使用
}
/**
* 定期更新Oss Sts token
*
* @return mixed
*/
private function handle()
{
if($this->redis->exists(self::OSS_STS_TOKEN)) {
return $this->redis->get(self::OSS_STS_TOKEN);
}
date_default_timezone_set("GMT");
$params = [
// 获取公共参数
'Format' => self::FORMAT,
'Version' => self::VERSION,
'AccessKeyId' => self::OSS_STS_ACCESS_ID,
'SignatureMethod' => self::SIGN_ATURE_METHOD,
'SignatureVersion' => self::SIGN_ATURE_VERSION,
'SignatureNonce' => uniqid(),
'Timestamp' => date('Y-m-dTH:i:s'),
// 获取接口参数
'Action' => 'AssumeRole',
'RoleArn' => self::OSS_ARN,
'RoleSessionName' => self::ROLE_SESSION_NAME,
];
ksort($params);
$oss_access_key = self::OSS_ACCESE_SECRET;
$sign = '';
$items = [];
foreach($params as $key => $value){
$items[] = rawurlencode($key) . '=' . rawurlencode($value);
$sign .= '&' . $this->percentEncode($key). '=' . $this->percentEncode($value);
}
$sign = 'GET&%2F&' . $this->percentencode(substr($sign, 1));
$signature = base64_encode(hash_hmac('sha1', $sign, $oss_access_key . "&", true));
$url = self::OSS_STS_URL . '?' . implode('&', $items) . '&Signature=' . rawurlencode($signature);
$token = $this->getApi($url);
$time = date('Y-m-d H:i:s', time());
if (!empty($token)) {
$this->redis->set(self::OSS_STS_TOKEN, $token, self::OSS_TIME);
return $token;
}
}
private function percentEncode($str)
{
$res = urlencode($str);
$res = preg_replace('/+/', '%20', $res);
$res = preg_replace('/*/', '%2A', $res);
$res = preg_replace('/%7E/', '~', $res);
return $res;
}
private function getApi($url){
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$output = curl_exec($ch);
curl_close($ch);
$output = json_decode($output,true);
if(!isset($output['Credentials'])){
return false;
}else{
return $output['Credentials'];
}
}
}