sts.php 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. <?php
  2. class STS{
  3. // 临时密钥计算样例
  4. function _hex2bin($data) {
  5. $len = strlen($data);
  6. return pack("H" . $len, $data);
  7. }
  8. // obj 转 query string
  9. function json2str($obj, $notEncode = false) {
  10. ksort($obj);
  11. $arr = array();
  12. if(!is_array($obj)){
  13. throw new Exception($obj + " must be a array");
  14. }
  15. foreach ($obj as $key => $val) {
  16. array_push($arr, $key . '=' . ($notEncode ? $val : rawurlencode($val)));
  17. }
  18. return join('&', $arr);
  19. }
  20. // 计算临时密钥用的签名
  21. function getSignature($opt, $key, $method, $config) {
  22. $formatString = $method . $config['domain'] . '/?' . $this->json2str($opt, 1);
  23. $sign = hash_hmac('sha1', $formatString, $key);
  24. $sign = base64_encode($this->_hex2bin($sign));
  25. return $sign;
  26. }
  27. // v2接口的key首字母小写,v3改成大写,此处做了向下兼容
  28. function backwardCompat($result) {
  29. if(!is_array($result)){
  30. throw new Exception($result + " must be a array");
  31. }
  32. $compat = array();
  33. foreach ($result as $key => $value) {
  34. if(is_array($value)) {
  35. $compat[lcfirst($key)] = $this->backwardCompat($value);
  36. } elseif ($key == 'Token') {
  37. $compat['sessionToken'] = $value;
  38. } else {
  39. $compat[lcfirst($key)] = $value;
  40. }
  41. }
  42. return $compat;
  43. }
  44. // 获取临时密钥
  45. function getTempKeys($config) {
  46. $result = null;
  47. try{
  48. if(array_key_exists('policy', $config)){
  49. $policy = $config['policy'];
  50. }else{
  51. if(array_key_exists('bucket', $config)){
  52. $ShortBucketName = substr($config['bucket'],0, strripos($config['bucket'], '-'));
  53. $AppId = substr($config['bucket'], 1 + strripos($config['bucket'], '-'));
  54. }else{
  55. throw new Exception("bucket== null");
  56. }
  57. if(array_key_exists('allowPrefix', $config)){
  58. if(!(strpos($config['allowPrefix'], '/') === 0)){
  59. $config['allowPrefix'] = '/' . $config['allowPrefix'];
  60. }
  61. }else{
  62. throw new Exception("allowPrefix == null");
  63. }
  64. $policy = array(
  65. 'version'=> '2.0',
  66. 'statement'=> array(
  67. array(
  68. 'action'=> $config['allowActions'],
  69. 'effect'=> 'allow',
  70. 'principal'=> array('qcs'=> array('*')),
  71. 'resource'=> array(
  72. 'qcs::cos:' . $config['region'] . ':uid/' . $AppId . ':' . $config['bucket'] . $config['allowPrefix']
  73. )
  74. )
  75. )
  76. );
  77. }
  78. $policyStr = str_replace('\\/', '/', json_encode($policy));
  79. $Action = 'GetFederationToken';
  80. $Nonce = rand(10000, 20000);
  81. $Timestamp = time();
  82. $Method = 'POST';
  83. if(array_key_exists('durationSeconds', $config)){
  84. if(!(is_integer($config['durationSeconds']))){
  85. throw new exception("durationSeconds must be a int type");
  86. }
  87. }
  88. $params = array(
  89. 'SecretId'=> $config['secretId'],
  90. 'Timestamp'=> $Timestamp,
  91. 'Nonce'=> $Nonce,
  92. 'Action'=> $Action,
  93. 'DurationSeconds'=> $config['durationSeconds'],
  94. 'Version'=>'2018-08-13',
  95. 'Name'=> 'cos',
  96. 'Region'=> $config['region'],
  97. 'Policy'=> urlencode($policyStr)
  98. );
  99. $params['Signature'] = $this->getSignature($params, $config['secretKey'], $Method, $config);
  100. $url = $config['url'];
  101. $ch = curl_init($url);
  102. if(array_key_exists('proxy', $config)){
  103. $config['proxy'] && curl_setopt($ch, CURLOPT_PROXY, $config['proxy']);
  104. }
  105. curl_setopt($ch, CURLOPT_HEADER, 0);
  106. curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,0);
  107. curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,0);
  108. curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  109. curl_setopt($ch, CURLOPT_POST, 1);
  110. curl_setopt($ch, CURLOPT_POSTFIELDS, $this->json2str($params));
  111. $result = curl_exec($ch);
  112. if(curl_errno($ch)) $result = curl_error($ch);
  113. curl_close($ch);
  114. $result = json_decode($result, 1);
  115. if (isset($result['Response'])) {
  116. $result = $result['Response'];
  117. if(isset($result['Error'])){
  118. throw new Exception("get cam failed");
  119. }
  120. $result['startTime'] = $result['ExpiredTime'] - $config['durationSeconds'];
  121. }
  122. $result = $this->backwardCompat($result);
  123. return $result;
  124. }catch(Exception $e){
  125. if($result == null){
  126. $result = "error: " . + $e->getMessage();
  127. }else{
  128. $result = json_encode($result);
  129. }
  130. throw new Exception($result);
  131. }
  132. }
  133. // get policy
  134. function getPolicy($scopes){
  135. if (!is_array($scopes)){
  136. return null;
  137. }
  138. $statements = array();
  139. for($i=0, $counts=count($scopes); $i < $counts; $i++){
  140. $actions=array();
  141. $resources = array();
  142. array_push($actions, $scopes[$i]->get_action());
  143. array_push($resources, $scopes[$i]->get_resource());
  144. $statement = array(
  145. 'actions' => $actions,
  146. 'effect' => $scopes[$i]->get_effect(),
  147. 'resource' => $resources
  148. );
  149. array_push($statements, $statement);
  150. }
  151. $policy = array(
  152. 'version' => '2.0',
  153. 'statement' => $statements
  154. );
  155. return $policy;
  156. }
  157. }
  158. class Scope{
  159. var $action;
  160. var $bucket;
  161. var $region;
  162. var $resourcePrefix;
  163. var $effect = 'allow';
  164. function __construct($action, $bucket, $region, $resourcePrefix){
  165. $this->action = $action;
  166. $this->bucket = $bucket;
  167. $this->region = $region;
  168. $this->resourcePrefix = $resourcePrefix;
  169. }
  170. function set_effect($isAllow){
  171. if($isAllow){
  172. $this->effect = 'allow';
  173. }else{
  174. $this->effect = 'deny';
  175. }
  176. }
  177. function get_action(){
  178. if($this->action == null){
  179. throw new Exception("action == null");
  180. }
  181. return $this->action;
  182. }
  183. function get_resource(){
  184. if($this->bucket == null){
  185. throw new Exception("bucket == null");
  186. }
  187. if($this->resourcePrefix == null){
  188. throw new Exception("resourcePrefix == null");
  189. }
  190. $index = strripos($this->bucket, '-');
  191. if($index < 0){
  192. throw new Exception("bucket is invalid: " + $this->bucket);
  193. }
  194. $appid = substr($this->bucket, $index + 1);
  195. if(!(strpos($this->resourcePrefix, '/') === 0)){
  196. $this->resourcePrefix = '/' . $this->resourcePrefix;
  197. }
  198. return 'qcs::cos:' . $this->region . ':uid/' . $appid . ':' . $this->bucket . $this->resourcePrefix;
  199. }
  200. function get_effect(){
  201. return $this->effect;
  202. }
  203. }
  204. ?>