1 | <?php |
||
2 | namespace Qiniu; |
||
3 | |||
4 | use Qiniu\Http\Header; |
||
5 | use Qiniu\Zone; |
||
6 | |||
7 | final class Auth |
||
8 | { |
||
9 | private $accessKey; |
||
10 | private $secretKey; |
||
11 | |||
12 | public function __construct($accessKey, $secretKey) |
||
13 | { |
||
14 | $this->accessKey = $accessKey; |
||
15 | $this->secretKey = $secretKey; |
||
16 | } |
||
17 | 6 | ||
18 | public function getAccessKey() |
||
19 | 6 | { |
|
20 | return $this->accessKey; |
||
21 | } |
||
22 | 93 | ||
23 | public function sign($data) |
||
24 | 93 | { |
|
25 | 93 | $hmac = hash_hmac('sha1', $data, $this->secretKey, true); |
|
26 | return $this->accessKey . ':' . \Qiniu\base64_urlSafeEncode($hmac); |
||
27 | } |
||
28 | 24 | ||
29 | public function signWithData($data) |
||
30 | 24 | { |
|
31 | 24 | $encodedData = \Qiniu\base64_urlSafeEncode($data); |
|
32 | return $this->sign($encodedData) . ':' . $encodedData; |
||
33 | } |
||
34 | 54 | ||
35 | public function signRequest($urlString, $body, $contentType = null) |
||
36 | 54 | { |
|
37 | 54 | $url = parse_url($urlString); |
|
38 | 54 | $data = ''; |
|
39 | 51 | if (array_key_exists('path', $url)) { |
|
40 | 51 | $data = $url['path']; |
|
41 | 54 | } |
|
42 | 9 | if (array_key_exists('query', $url)) { |
|
43 | 9 | $data .= '?' . $url['query']; |
|
44 | 54 | } |
|
45 | $data .= "\n"; |
||
46 | 54 | ||
47 | 24 | if ($body !== null && $contentType === 'application/x-www-form-urlencoded') { |
|
48 | 24 | $data .= $body; |
|
49 | 54 | } |
|
50 | return $this->sign($data); |
||
51 | } |
||
52 | |||
53 | /** |
||
54 | * @param string $urlString |
||
55 | * @param string $method |
||
56 | * @param string $body |
||
57 | * @param null|Header $headers |
||
58 | 12 | */ |
|
59 | public function signQiniuAuthorization($urlString, $method = "GET", $body = "", $headers = null) |
||
60 | 12 | { |
|
61 | $url = parse_url($urlString); |
||
62 | 12 | if (!$url) { |
|
63 | 12 | return array(null, new \Exception("parse_url error")); |
|
64 | 9 | } |
|
65 | 9 | ||
66 | 3 | // append method, path and query |
|
67 | if ($method === "") { |
||
68 | 12 | $data = "GET "; |
|
69 | } else { |
||
70 | 12 | $data = $method . " "; |
|
71 | 12 | } |
|
72 | if (isset($url["path"])) { |
||
73 | $data .= $url["path"]; |
||
74 | 21 | } |
|
75 | if (isset($url["query"])) { |
||
76 | 21 | $data .= "?" . $url["query"]; |
|
77 | 21 | } |
|
78 | 21 | ||
79 | 15 | // append Host |
|
80 | 15 | $data .= "\n"; |
|
81 | $data .= "Host: "; |
||
82 | 21 | if (isset($url["host"])) { |
|
83 | 21 | $data .= $url["host"]; |
|
84 | 21 | } |
|
85 | if (isset($url["port"]) && $url["port"] > 0) { |
||
86 | 21 | $data .= ":" . $url["port"]; |
|
87 | 21 | } |
|
88 | |||
89 | // try append content type |
||
90 | if ($headers != null && isset($headers["Content-Type"])) { |
||
91 | // append content type |
||
92 | $data .= "\n"; |
||
93 | $data .= "Content-Type: " . $headers["Content-Type"]; |
||
94 | } |
||
95 | |||
96 | // try append xQiniuHeaders |
||
97 | if ($headers != null) { |
||
98 | $headerLines = array(); |
||
99 | $keyPrefix = "X-Qiniu-"; |
||
100 | foreach ($headers as $k => $v) { |
||
101 | if (strlen($k) > strlen($keyPrefix) && strpos($k, $keyPrefix) === 0) { |
||
102 | array_push( |
||
103 | $headerLines, |
||
104 | $k . ": " . $v |
||
105 | ); |
||
106 | } |
||
107 | } |
||
108 | if (count($headerLines) > 0) { |
||
109 | $data .= "\n"; |
||
110 | sort($headerLines); |
||
111 | $data .= implode("\n", $headerLines); |
||
112 | } |
||
113 | } |
||
114 | |||
115 | // append body |
||
116 | $data .= "\n\n"; |
||
117 | if (count($body) > 0 |
||
0 ignored issues
–
show
Bug
introduced
by
Loading history...
|
|||
118 | && isset($headers["Content-Type"]) |
||
119 | && $headers["Content-Type"] != "application/octet-stream" |
||
120 | ) { |
||
121 | $data .= $body; |
||
122 | 21 | } |
|
123 | |||
124 | 21 | return array($this->sign(utf8_encode($data)), null); |
|
125 | 18 | } |
|
126 | |||
127 | 3 | public function verifyCallback($contentType, $originAuthorization, $url, $body) |
|
128 | 3 | { |
|
129 | 3 | $authorization = 'QBox ' . $this->signRequest($url, $body, $contentType); |
|
130 | 3 | return $originAuthorization === $authorization; |
|
131 | 3 | } |
|
132 | 3 | ||
133 | public function privateDownloadUrl($baseUrl, $expires = 3600) |
||
134 | { |
||
135 | 51 | $deadline = time() + $expires; |
|
136 | |||
137 | 51 | $pos = strpos($baseUrl, '?'); |
|
138 | 51 | if ($pos !== false) { |
|
139 | $baseUrl .= '&e='; |
||
140 | } else { |
||
141 | $baseUrl .= '?e='; |
||
142 | } |
||
143 | $baseUrl .= $deadline; |
||
144 | |||
145 | $token = $this->sign($baseUrl); |
||
146 | return "$baseUrl&token=$token"; |
||
147 | } |
||
148 | |||
149 | public function uploadToken($bucket, $key = null, $expires = 3600, $policy = null, $strictPolicy = true) |
||
150 | { |
||
151 | $deadline = time() + $expires; |
||
152 | $scope = $bucket; |
||
153 | if ($key !== null) { |
||
154 | $scope .= ':' . $key; |
||
155 | } |
||
156 | |||
157 | $args = self::copyPolicy($args, $policy, $strictPolicy); |
||
158 | $args['scope'] = $scope; |
||
159 | $args['deadline'] = $deadline; |
||
160 | |||
161 | $b = json_encode($args); |
||
162 | return $this->signWithData($b); |
||
163 | } |
||
164 | |||
165 | /** |
||
166 | *上传策略,参数规格详见 |
||
167 | *http://developer.qiniu.com/docs/v6/api/reference/security/put-policy.html |
||
168 | */ |
||
169 | private static $policyFields = array( |
||
170 | 'callbackUrl', |
||
171 | 'callbackBody', |
||
172 | 'callbackHost', |
||
173 | 'callbackBodyType', |
||
174 | 'callbackFetchKey', |
||
175 | |||
176 | 'returnUrl', |
||
177 | 'returnBody', |
||
178 | |||
179 | 'endUser', |
||
180 | 'saveKey', |
||
181 | 'forceSaveKey', |
||
182 | 'insertOnly', |
||
183 | |||
184 | 'detectMime', |
||
185 | 'mimeLimit', |
||
186 | 'fsizeMin', |
||
187 | 'fsizeLimit', |
||
188 | |||
189 | 'persistentOps', |
||
190 | 'persistentNotifyUrl', |
||
191 | 'persistentPipeline', |
||
192 | |||
193 | 'deleteAfterDays', |
||
194 | 'fileType', |
||
195 | 'isPrefixalScope', |
||
196 | ); |
||
197 | |||
198 | private static function copyPolicy(&$policy, $originPolicy, $strictPolicy) |
||
199 | { |
||
200 | if ($originPolicy === null) { |
||
201 | return array(); |
||
202 | } |
||
203 | foreach ($originPolicy as $key => $value) { |
||
204 | if (!$strictPolicy || in_array((string)$key, self::$policyFields, true)) { |
||
205 | $policy[$key] = $value; |
||
206 | } |
||
207 | } |
||
208 | return $policy; |
||
209 | } |
||
210 | |||
211 | public function authorization($url, $body = null, $contentType = null) |
||
212 | { |
||
213 | $authorization = 'QBox ' . $this->signRequest($url, $body, $contentType); |
||
214 | return array('Authorization' => $authorization); |
||
215 | } |
||
216 | |||
217 | public function authorizationV2($url, $method, $body = null, $contentType = null) |
||
218 | { |
||
219 | $headers = null; |
||
220 | $result = array(); |
||
221 | if ($contentType != null) { |
||
222 | $headers = new Header(array( |
||
223 | 'Content-Type' => array($contentType), |
||
224 | )); |
||
225 | $result['Content-Type'] = $contentType; |
||
226 | } |
||
227 | list($sign) = $this->signQiniuAuthorization($url, $method, $body, $headers); |
||
228 | $result['Authorization'] = 'Qiniu ' . $sign; |
||
229 | return $result; |
||
230 | } |
||
231 | } |
||
232 |