Completed
Push — master ( 4db7bf...47f9e5 )
by
unknown
16s queued 13s
created

Auth::authorizationV2()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 13
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 2
eloc 9
nc 2
nop 4
dl 0
loc 13
ccs 0
cts 0
cp 0
crap 6
rs 9.9666
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 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
$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

117
        if (count(/** @scrutinizer ignore-type */ $body) > 0
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