Passed
Pull Request — master (#373)
by
unknown
22:11
created

Auth::authorizationV2()   B

Complexity

Conditions 7
Paths 64

Size

Total Lines 45
Code Lines 25

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 56

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 7
eloc 25
nc 64
nop 4
dl 0
loc 45
ccs 0
cts 0
cp 0
crap 56
rs 8.5866
c 1
b 0
f 1
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) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $url of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

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.

Loading history...
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->getRawData() as $k => $vs) {
101
                if (strlen($k) > strlen($keyPrefix) && strpos($k, $keyPrefix) === 0) {
102
                    foreach ($vs as $v) {
103
                        array_push(
104
                            $headerLines,
105
                            $k . ": " . $v
106
                        );
107
                    }
108
                }
109
            }
110
            if (count($headerLines) > 0) {
111
                $data .= "\n";
112
                sort($headerLines);
113
                $data .= implode("\n", $headerLines);
114
            }
115
        }
116
117
        // append body
118
        $data .= "\n\n";
119
        if (count($body) > 0
0 ignored issues
show
Bug introduced by
$body of type string is incompatible with the type Countable|array expected by parameter $value of count(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

119
        if (count(/** @scrutinizer ignore-type */ $body) > 0
Loading history...
120
            && isset($headers["Content-Type"])
121
            && $headers["Content-Type"] != "application/octet-stream"
122 21
        ) {
123
            $data .= $body;
124 21
        }
125 18
126
        return array($this->sign(utf8_encode($data)), null);
127 3
    }
128 3
129 3
    public function verifyCallback($contentType, $originAuthorization, $url, $body)
130 3
    {
131 3
        $authorization = 'QBox ' . $this->signRequest($url, $body, $contentType);
132 3
        return $originAuthorization === $authorization;
133
    }
134
135 51
    public function privateDownloadUrl($baseUrl, $expires = 3600)
136
    {
137 51
        $deadline = time() + $expires;
138 51
139
        $pos = strpos($baseUrl, '?');
140
        if ($pos !== false) {
141
            $baseUrl .= '&e=';
142
        } else {
143
            $baseUrl .= '?e=';
144
        }
145
        $baseUrl .= $deadline;
146
147
        $token = $this->sign($baseUrl);
148
        return "$baseUrl&token=$token";
149
    }
150
151
    public function uploadToken($bucket, $key = null, $expires = 3600, $policy = null, $strictPolicy = true)
152
    {
153
        $deadline = time() + $expires;
154
        $scope = $bucket;
155
        if ($key !== null) {
156
            $scope .= ':' . $key;
157
        }
158
159
        $args = self::copyPolicy($args, $policy, $strictPolicy);
160
        $args['scope'] = $scope;
161
        $args['deadline'] = $deadline;
162
163
        $b = json_encode($args);
164
        return $this->signWithData($b);
165
    }
166
167
    /**
168
     *上传策略,参数规格详见
169
     *http://developer.qiniu.com/docs/v6/api/reference/security/put-policy.html
170
     */
171
    private static $policyFields = array(
172
        'callbackUrl',
173
        'callbackBody',
174
        'callbackHost',
175
        'callbackBodyType',
176
        'callbackFetchKey',
177
178
        'returnUrl',
179
        'returnBody',
180
181
        'endUser',
182
        'saveKey',
183
        'forceSaveKey',
184
        'insertOnly',
185
186
        'detectMime',
187
        'mimeLimit',
188
        'fsizeMin',
189
        'fsizeLimit',
190
191
        'persistentOps',
192
        'persistentNotifyUrl',
193
        'persistentPipeline',
194
195
        'deleteAfterDays',
196
        'fileType',
197
        'isPrefixalScope',
198
    );
199
200
    private static function copyPolicy(&$policy, $originPolicy, $strictPolicy)
201
    {
202
        if ($originPolicy === null) {
203
            return array();
204
        }
205
        foreach ($originPolicy as $key => $value) {
206
            if (!$strictPolicy || in_array((string)$key, self::$policyFields, true)) {
207
                $policy[$key] = $value;
208
            }
209
        }
210
        return $policy;
211
    }
212
213
    public function authorization($url, $body = null, $contentType = null)
214
    {
215
        $authorization = 'QBox ' . $this->signRequest($url, $body, $contentType);
216
        return array('Authorization' => $authorization);
217
    }
218
219
    public function authorizationV2($url, $method, $body = null, $contentType = null)
220
    {
221
        $urlItems = parse_url($url);
222
        $host = $urlItems['host'];
223
224
        if (isset($urlItems['port'])) {
225
            $port = $urlItems['port'];
226
        } else {
227
            $port = '';
228
        }
229
230
        $path = $urlItems['path'];
231
        if (isset($urlItems['query'])) {
232
            $query = $urlItems['query'];
233
        } else {
234
            $query = '';
235
        }
236
237
        //write request uri
238
        $toSignStr = $method . ' ' . $path;
239
        if (!empty($query)) {
240
            $toSignStr .= '?' . $query;
241
        }
242
243
        //write host and port
244
        $toSignStr .= "\nHost: " . $host;
245
        if (!empty($port)) {
246
            $toSignStr .= ":" . $port;
247
        }
248
249
        //write content type
250
        if (!empty($contentType)) {
251
            $toSignStr .= "\nContent-Type: " . $contentType;
252
        }
253
254
        $toSignStr .= "\n\n";
255
256
        //write body
257
        if (!empty($body)) {
258
            $toSignStr .= $body;
259
        }
260
261
        $sign = $this->sign($toSignStr);
262
        $auth = 'Qiniu ' . $sign;
263
        return array('Authorization' => $auth);
264
    }
265
}
266