qiniu /
php-sdk
| 1 | <?php |
||
| 2 | |||
| 3 | namespace Qiniu; |
||
| 4 | |||
| 5 | use Qiniu\Http\Header; |
||
| 6 | use Qiniu\Zone; |
||
| 7 | |||
| 8 | final class Auth |
||
| 9 | { |
||
| 10 | private $accessKey; |
||
| 11 | private $secretKey; |
||
| 12 | public $options; |
||
| 13 | |||
| 14 | public function __construct($accessKey, $secretKey, $options = null) |
||
| 15 | { |
||
| 16 | $this->accessKey = $accessKey; |
||
| 17 | 6 | $this->secretKey = $secretKey; |
|
| 18 | $defaultOptions = array( |
||
| 19 | 6 | 'disableQiniuTimestampSignature' => null |
|
| 20 | ); |
||
| 21 | if ($options == null) { |
||
| 22 | 93 | $options = $defaultOptions; |
|
| 23 | } |
||
| 24 | 93 | $this->options = array_merge($defaultOptions, $options); |
|
| 25 | 93 | } |
|
| 26 | |||
| 27 | public function getAccessKey() |
||
| 28 | 24 | { |
|
| 29 | return $this->accessKey; |
||
| 30 | 24 | } |
|
| 31 | 24 | ||
| 32 | public function sign($data) |
||
| 33 | { |
||
| 34 | 54 | $hmac = hash_hmac('sha1', $data, $this->secretKey, true); |
|
| 35 | return $this->accessKey . ':' . \Qiniu\base64_urlSafeEncode($hmac); |
||
| 36 | 54 | } |
|
| 37 | 54 | ||
| 38 | 54 | public function signWithData($data) |
|
| 39 | 51 | { |
|
| 40 | 51 | $encodedData = \Qiniu\base64_urlSafeEncode($data); |
|
| 41 | 54 | return $this->sign($encodedData) . ':' . $encodedData; |
|
| 42 | 9 | } |
|
| 43 | 9 | ||
| 44 | 54 | public function signRequest($urlString, $body, $contentType = null) |
|
| 45 | { |
||
| 46 | 54 | $url = parse_url($urlString); |
|
| 47 | 24 | $data = ''; |
|
| 48 | 24 | if (array_key_exists('path', $url)) { |
|
| 49 | 54 | $data = $url['path']; |
|
| 50 | } |
||
| 51 | if (array_key_exists('query', $url)) { |
||
| 52 | $data .= '?' . $url['query']; |
||
| 53 | } |
||
| 54 | $data .= "\n"; |
||
| 55 | |||
| 56 | if ($body !== null && $contentType === 'application/x-www-form-urlencoded') { |
||
| 57 | $data .= $body; |
||
| 58 | 12 | } |
|
| 59 | return $this->sign($data); |
||
| 60 | 12 | } |
|
| 61 | |||
| 62 | 12 | /** |
|
| 63 | 12 | * @param string $urlString |
|
| 64 | 9 | * @param string $method |
|
| 65 | 9 | * @param string $body |
|
| 66 | 3 | * @param null|Header $headers |
|
| 67 | */ |
||
| 68 | 12 | public function signQiniuAuthorization($urlString, $method = "GET", $body = "", $headers = null) |
|
| 69 | { |
||
| 70 | 12 | $url = parse_url($urlString); |
|
| 71 | 12 | if (!$url) { |
|
|
0 ignored issues
–
show
|
|||
| 72 | return array(null, new \Exception("parse_url error")); |
||
| 73 | } |
||
| 74 | 21 | ||
| 75 | // append method, path and query |
||
| 76 | 21 | if ($method === "") { |
|
| 77 | 21 | $data = "GET "; |
|
| 78 | 21 | } else { |
|
| 79 | 15 | $data = $method . " "; |
|
| 80 | 15 | } |
|
| 81 | if (isset($url["path"])) { |
||
| 82 | 21 | $data .= $url["path"]; |
|
| 83 | 21 | } |
|
| 84 | 21 | if (isset($url["query"])) { |
|
| 85 | $data .= "?" . $url["query"]; |
||
| 86 | 21 | } |
|
| 87 | 21 | ||
| 88 | // append Host |
||
| 89 | $data .= "\n"; |
||
| 90 | $data .= "Host: "; |
||
| 91 | if (isset($url["host"])) { |
||
| 92 | $data .= $url["host"]; |
||
| 93 | } |
||
| 94 | if (isset($url["port"]) && $url["port"] > 0) { |
||
| 95 | $data .= ":" . $url["port"]; |
||
| 96 | } |
||
| 97 | |||
| 98 | // try to append content type |
||
| 99 | if ($headers != null && isset($headers["Content-Type"])) { |
||
| 100 | // append content type |
||
| 101 | $data .= "\n"; |
||
| 102 | $data .= "Content-Type: " . $headers["Content-Type"]; |
||
| 103 | } |
||
| 104 | |||
| 105 | // try append xQiniuHeaders |
||
| 106 | if ($headers != null) { |
||
| 107 | $headerLines = array(); |
||
| 108 | $keyPrefix = "X-Qiniu-"; |
||
| 109 | foreach ($headers as $k => $v) { |
||
| 110 | if (strlen($k) > strlen($keyPrefix) && strpos($k, $keyPrefix) === 0) { |
||
| 111 | array_push( |
||
| 112 | $headerLines, |
||
| 113 | $k . ": " . $v |
||
| 114 | ); |
||
| 115 | } |
||
| 116 | } |
||
| 117 | if (count($headerLines) > 0) { |
||
| 118 | $data .= "\n"; |
||
| 119 | sort($headerLines); |
||
| 120 | $data .= implode("\n", $headerLines); |
||
| 121 | } |
||
| 122 | 21 | } |
|
| 123 | |||
| 124 | 21 | // append body |
|
| 125 | 18 | $data .= "\n\n"; |
|
| 126 | if (!is_null($body) |
||
|
0 ignored issues
–
show
|
|||
| 127 | 3 | && strlen($body) > 0 |
|
| 128 | 3 | && isset($headers["Content-Type"]) |
|
| 129 | 3 | && $headers["Content-Type"] != "application/octet-stream" |
|
| 130 | 3 | ) { |
|
| 131 | 3 | $data .= $body; |
|
| 132 | 3 | } |
|
| 133 | |||
| 134 | return array($this->sign($data), null); |
||
| 135 | 51 | } |
|
| 136 | |||
| 137 | 51 | public function verifyCallback( |
|
| 138 | 51 | $contentType, |
|
| 139 | $originAuthorization, |
||
| 140 | $url, |
||
| 141 | $body, |
||
| 142 | $method = "GET", |
||
| 143 | $headers = array() |
||
| 144 | ) { |
||
| 145 | if (strpos($originAuthorization, 'Qiniu') === 0) { |
||
| 146 | $qnHeaders = new Header($headers); |
||
| 147 | if (!isset($qnHeaders['Content-Type'])) { |
||
| 148 | $qnHeaders['Content-Type'] = $contentType; |
||
| 149 | } |
||
| 150 | list($sign, $err) = $this->signQiniuAuthorization( |
||
| 151 | $url, |
||
| 152 | $method, |
||
| 153 | $body, |
||
| 154 | $qnHeaders |
||
| 155 | ); |
||
| 156 | if ($err !== null) { |
||
| 157 | return false; |
||
| 158 | } |
||
| 159 | $authorization = 'Qiniu ' . $sign; |
||
| 160 | } else { |
||
| 161 | $authorization = 'QBox ' . $this->signRequest($url, $body, $contentType); |
||
| 162 | } |
||
| 163 | return $originAuthorization === $authorization; |
||
| 164 | } |
||
| 165 | |||
| 166 | public function privateDownloadUrl($baseUrl, $expires = 3600) |
||
| 167 | { |
||
| 168 | $deadline = time() + $expires; |
||
| 169 | |||
| 170 | $pos = strpos($baseUrl, '?'); |
||
| 171 | if ($pos !== false) { |
||
| 172 | $baseUrl .= '&e='; |
||
| 173 | } else { |
||
| 174 | $baseUrl .= '?e='; |
||
| 175 | } |
||
| 176 | $baseUrl .= $deadline; |
||
| 177 | |||
| 178 | $token = $this->sign($baseUrl); |
||
| 179 | return "$baseUrl&token=$token"; |
||
| 180 | } |
||
| 181 | |||
| 182 | public function uploadToken($bucket, $key = null, $expires = 3600, $policy = null, $strictPolicy = true) |
||
| 183 | { |
||
| 184 | $deadline = time() + $expires; |
||
| 185 | $scope = $bucket; |
||
| 186 | if ($key !== null) { |
||
| 187 | $scope .= ':' . $key; |
||
| 188 | } |
||
| 189 | |||
| 190 | $args = self::copyPolicy($args, $policy, $strictPolicy); |
||
| 191 | $args['scope'] = $scope; |
||
| 192 | $args['deadline'] = $deadline; |
||
| 193 | |||
| 194 | $b = json_encode($args); |
||
| 195 | return $this->signWithData($b); |
||
| 196 | } |
||
| 197 | |||
| 198 | /** |
||
| 199 | *上传策略,参数规格详见 |
||
| 200 | *http://developer.qiniu.com/docs/v6/api/reference/security/put-policy.html |
||
| 201 | */ |
||
| 202 | private static $policyFields = array( |
||
| 203 | 'callbackUrl', |
||
| 204 | 'callbackBody', |
||
| 205 | 'callbackHost', |
||
| 206 | 'callbackBodyType', |
||
| 207 | 'callbackFetchKey', |
||
| 208 | |||
| 209 | 'returnUrl', |
||
| 210 | 'returnBody', |
||
| 211 | |||
| 212 | 'endUser', |
||
| 213 | 'saveKey', |
||
| 214 | 'forceSaveKey', |
||
| 215 | 'insertOnly', |
||
| 216 | |||
| 217 | 'detectMime', |
||
| 218 | 'mimeLimit', |
||
| 219 | 'fsizeMin', |
||
| 220 | 'fsizeLimit', |
||
| 221 | |||
| 222 | 'persistentOps', // 与 persistentWorkflowTemplateID 二选一 |
||
| 223 | 'persistentNotifyUrl', |
||
| 224 | 'persistentPipeline', |
||
| 225 | 'persistentType', // 为 `1` 时开启闲时任务 |
||
| 226 | 'persistentWorkflowTemplateID', // 与 persistentOps 二选一 |
||
| 227 | |||
| 228 | 'deleteAfterDays', |
||
| 229 | 'fileType', |
||
| 230 | 'isPrefixalScope', |
||
| 231 | |||
| 232 | 'transform', // deprecated |
||
| 233 | 'transformFallbackKey', // deprecated |
||
| 234 | 'transformFallbackMode', // deprecated |
||
| 235 | ); |
||
| 236 | |||
| 237 | private static function copyPolicy(&$policy, $originPolicy, $strictPolicy) |
||
| 238 | { |
||
| 239 | if ($originPolicy === null) { |
||
| 240 | return array(); |
||
| 241 | } |
||
| 242 | foreach ($originPolicy as $key => $value) { |
||
| 243 | if (!$strictPolicy || in_array((string)$key, self::$policyFields, true)) { |
||
| 244 | $policy[$key] = $value; |
||
| 245 | } |
||
| 246 | } |
||
| 247 | return $policy; |
||
| 248 | } |
||
| 249 | |||
| 250 | public function authorization($url, $body = null, $contentType = null) |
||
| 251 | { |
||
| 252 | $authorization = 'QBox ' . $this->signRequest($url, $body, $contentType); |
||
| 253 | return array('Authorization' => $authorization); |
||
| 254 | } |
||
| 255 | |||
| 256 | public function authorizationV2($url, $method, $body = null, $contentType = null) |
||
| 257 | { |
||
| 258 | $headers = new Header(); |
||
| 259 | $result = array(); |
||
| 260 | if ($contentType != null) { |
||
| 261 | $headers['Content-Type'] = $contentType; |
||
| 262 | $result['Content-Type'] = $contentType; |
||
| 263 | } |
||
| 264 | |||
| 265 | $signDate = gmdate('Ymd\THis\Z', time()); |
||
| 266 | if ($this->options['disableQiniuTimestampSignature'] !== null) { |
||
| 267 | if (!$this->options['disableQiniuTimestampSignature']) { |
||
| 268 | $headers['X-Qiniu-Date'] = $signDate; |
||
| 269 | $result['X-Qiniu-Date'] = $signDate; |
||
| 270 | } |
||
| 271 | } elseif (getenv("DISABLE_QINIU_TIMESTAMP_SIGNATURE")) { |
||
| 272 | if (strtolower(getenv("DISABLE_QINIU_TIMESTAMP_SIGNATURE")) !== "true") { |
||
| 273 | $headers['X-Qiniu-Date'] = $signDate; |
||
| 274 | $result['X-Qiniu-Date'] = $signDate; |
||
| 275 | } |
||
| 276 | } else { |
||
| 277 | $headers['X-Qiniu-Date'] = $signDate; |
||
| 278 | $result['X-Qiniu-Date'] = $signDate; |
||
| 279 | } |
||
| 280 | |||
| 281 | list($sign) = $this->signQiniuAuthorization($url, $method, $body, $headers); |
||
| 282 | $result['Authorization'] = 'Qiniu ' . $sign; |
||
| 283 | return $result; |
||
| 284 | } |
||
| 285 | } |
||
| 286 |
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)or! empty(...)instead.