Signature.php 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. <?php
  2. namespace Qcloud\Cos;
  3. use Psr\Http\Message\RequestInterface;
  4. class Signature {
  5. // string: access key.
  6. private $accessKey;
  7. // string: secret key.
  8. private $secretKey;
  9. // array: cos config.
  10. private $options;
  11. public function __construct( $accessKey, $secretKey, $options, $token = null ) {
  12. $this->accessKey = $accessKey;
  13. $this->secretKey = $secretKey;
  14. $this->options = $options;
  15. $this->token = $token;
  16. $this->signHeader = [
  17. 'cache-control',
  18. 'content-disposition',
  19. 'content-encoding',
  20. 'content-length',
  21. 'content-md5',
  22. 'content-type',
  23. 'expect',
  24. 'expires',
  25. 'host',
  26. 'if-match',
  27. 'if-modified-since',
  28. 'if-none-match',
  29. 'if-unmodified-since',
  30. 'origin',
  31. 'range',
  32. 'response-cache-control',
  33. 'response-content-disposition',
  34. 'response-content-encoding',
  35. 'response-content-language',
  36. 'response-content-type',
  37. 'response-expires',
  38. 'transfer-encoding',
  39. 'versionid',
  40. ];
  41. date_default_timezone_set( 'PRC' );
  42. }
  43. public function __destruct() {
  44. }
  45. public function needCheckHeader( $header ) {
  46. if ( startWith( $header, 'x-cos-' ) ) {
  47. return true;
  48. }
  49. if ( in_array( $header, $this->signHeader ) ) {
  50. return true;
  51. }
  52. return false;
  53. }
  54. public function signRequest( RequestInterface $request ) {
  55. $authorization = $this->createAuthorization( $request );
  56. return $request->withHeader( 'Authorization', $authorization );
  57. }
  58. public function createAuthorization( RequestInterface $request, $expires = '+30 minutes' ) {
  59. if ( is_null( $expires ) || !strtotime( $expires )) {
  60. $expires = '+30 minutes';
  61. }
  62. $signTime = ( string )( time() - 60 ) . ';' . ( string )( strtotime( $expires ) );
  63. $urlParamListArray = [];
  64. foreach ( explode( '&', $request->getUri()->getQuery() ) as $query ) {
  65. if (!empty($query)) {
  66. $tmpquery = explode( '=', $query );
  67. //为了保证CI的key中有=号的情况也能正常通过,ci在这层之前已经encode了,这里需要拆开重新encode,防止上方explode拆错
  68. $key = strtolower( rawurlencode(urldecode($tmpquery[0])) );
  69. if (count($tmpquery) >= 2) {
  70. $value = $tmpquery[1];
  71. } else {
  72. $value = "";
  73. }
  74. //host开关
  75. if (!$this->options['signHost'] && $key == 'host') {
  76. continue;
  77. }
  78. $urlParamListArray[$key] = $key. '='. $value;
  79. }
  80. }
  81. ksort($urlParamListArray);
  82. $urlParamList = join(';', array_keys($urlParamListArray));
  83. $httpParameters = join('&', array_values($urlParamListArray));
  84. $headerListArray = [];
  85. foreach ( $request->getHeaders() as $key => $value ) {
  86. $key = strtolower( urlencode( $key ) );
  87. $value = rawurlencode( $value[0] );
  88. if ( !$this->options['signHost'] && $key == 'host' ) {
  89. continue;
  90. }
  91. if ( $this->needCheckHeader( $key ) ) {
  92. $headerListArray[$key] = $key. '='. $value;
  93. }
  94. }
  95. ksort($headerListArray);
  96. $headerList = join(';', array_keys($headerListArray));
  97. $httpHeaders = join('&', array_values($headerListArray));
  98. $httpString = strtolower( $request->getMethod() ) . "\n" . urldecode( $request->getUri()->getPath() ) . "\n" . $httpParameters.
  99. "\n". $httpHeaders. "\n";
  100. $sha1edHttpString = sha1( $httpString );
  101. $stringToSign = "sha1\n$signTime\n$sha1edHttpString\n";
  102. $signKey = hash_hmac( 'sha1', $signTime, trim($this->secretKey) );
  103. $signature = hash_hmac( 'sha1', $stringToSign, $signKey );
  104. $authorization = 'q-sign-algorithm=sha1&q-ak='. trim($this->accessKey) .
  105. "&q-sign-time=$signTime&q-key-time=$signTime&q-header-list=$headerList&q-url-param-list=$urlParamList&" .
  106. "q-signature=$signature";
  107. return $authorization;
  108. }
  109. public function createPresignedUrl( RequestInterface $request, $expires = '+30 minutes' ) {
  110. $authorization = $this->createAuthorization( $request, $expires);
  111. $uri = $request->getUri();
  112. $query = 'sign='.urlencode( $authorization ) . '&' . $uri->getQuery();
  113. if ( $this->token != null ) {
  114. $query = $query.'&x-cos-security-token='.$this->token;
  115. }
  116. $uri = $uri->withQuery( $query );
  117. return $uri;
  118. }
  119. }