88from .compat import urlquote , to_bytes , is_py2
99from .headers import *
1010import logging
11+ from .credentials import StaticCredentialsProvider
1112
1213AUTH_VERSION_1 = 'v1'
1314AUTH_VERSION_2 = 'v2'
@@ -26,11 +27,14 @@ def make_auth(access_key_id, access_key_secret, auth_version=AUTH_VERSION_1):
2627
2728class AuthBase (object ):
2829 """用于保存用户AccessKeyId、AccessKeySecret,以及计算签名的对象。"""
29- def __init__ (self , access_key_id , access_key_secret ):
30- self .id = access_key_id .strip ()
31- self .secret = access_key_secret .strip ()
30+ def __init__ (self , credentials_provider ):
31+ self .credentials_provider = credentials_provider
3232
3333 def _sign_rtmp_url (self , url , bucket_name , channel_name , expires , params ):
34+ credentials = self .credentials_provider .get_credentials ()
35+ if credentials .get_security_token ():
36+ params ['security-token' ] = credentials .get_security_token ()
37+
3438 expiration_time = int (time .time ()) + expires
3539
3640 canonicalized_resource = "/%s/%s" % (bucket_name , channel_name )
@@ -52,18 +56,21 @@ def _sign_rtmp_url(self, url, bucket_name, channel_name, expires, params):
5256 logger .debug ('Sign Rtmp url: string to be signed = {0}' .format (string_to_sign ))
5357
5458
55- h = hmac .new (to_bytes (self . secret ), to_bytes (string_to_sign ), hashlib .sha1 )
59+ h = hmac .new (to_bytes (credentials . get_access_key_secret () ), to_bytes (string_to_sign ), hashlib .sha1 )
5660 signature = utils .b64encode_as_string (h .digest ())
5761
58- p ['OSSAccessKeyId' ] = self . id
62+ p ['OSSAccessKeyId' ] = credentials . get_access_key_id ()
5963 p ['Expires' ] = str (expiration_time )
6064 p ['Signature' ] = signature
6165
6266 return url + '?' + '&' .join (_param_to_quoted_query (k , v ) for k , v in p .items ())
6367
6468
65- class Auth (AuthBase ):
66- """签名版本1"""
69+
70+ class ProviderAuth (AuthBase ):
71+ """签名版本1
72+ 默认构造函数同父类AuthBase,需要传递credentials_provider
73+ """
6774 _subresource_key_set = frozenset (
6875 ['response-content-type' , 'response-content-language' ,
6976 'response-cache-control' , 'logging' , 'response-content-encoding' ,
@@ -80,32 +87,40 @@ class Auth(AuthBase):
8087 )
8188
8289 def _sign_request (self , req , bucket_name , key ):
90+ credentials = self .credentials_provider .get_credentials ()
91+ if credentials .get_security_token ():
92+ req .headers [OSS_SECURITY_TOKEN ] = credentials .get_security_token ()
93+
8394 req .headers ['date' ] = utils .http_date ()
8495
85- signature = self .__make_signature (req , bucket_name , key )
86- req .headers ['authorization' ] = "OSS {0}:{1}" .format (self . id , signature )
96+ signature = self .__make_signature (req , bucket_name , key , credentials )
97+ req .headers ['authorization' ] = "OSS {0}:{1}" .format (credentials . get_access_key_id () , signature )
8798
8899 def _sign_url (self , req , bucket_name , key , expires ):
100+ credentials = self .credentials_provider .get_credentials ()
101+ if credentials .get_security_token ():
102+ req .params ['security-token' ] = credentials .get_security_token ()
103+
89104 expiration_time = int (time .time ()) + expires
90105
91106 req .headers ['date' ] = str (expiration_time )
92- signature = self .__make_signature (req , bucket_name , key )
107+ signature = self .__make_signature (req , bucket_name , key , credentials )
93108
94- req .params ['OSSAccessKeyId' ] = self . id
109+ req .params ['OSSAccessKeyId' ] = credentials . get_access_key_id ()
95110 req .params ['Expires' ] = str (expiration_time )
96111 req .params ['Signature' ] = signature
97112
98113 return req .url + '?' + '&' .join (_param_to_quoted_query (k , v ) for k , v in req .params .items ())
99114
100- def __make_signature (self , req , bucket_name , key ):
115+ def __make_signature (self , req , bucket_name , key , credentials ):
101116 if is_py2 :
102117 string_to_sign = self .__get_string_to_sign (req , bucket_name , key )
103118 else :
104119 string_to_sign = self .__get_bytes_to_sign (req , bucket_name , key )
105120
106121 logger .debug ('Make signature: string to be signed = {0}' .format (string_to_sign ))
107122
108- h = hmac .new (to_bytes (self . secret ), to_bytes (string_to_sign ), hashlib .sha1 )
123+ h = hmac .new (to_bytes (credentials . get_access_key_secret () ), to_bytes (string_to_sign ), hashlib .sha1 )
109124 return utils .b64encode_as_string (h .digest ())
110125
111126 def __get_string_to_sign (self , req , bucket_name , key ):
@@ -192,6 +207,14 @@ def __get_headers_bytes(self, req):
192207 else :
193208 return b''
194209
210+ class Auth (ProviderAuth ):
211+ """签名版本1
212+ """
213+ def __init__ (self , access_key_id , access_key_secret ):
214+ credentials_provider = StaticCredentialsProvider (access_key_id .strip (), access_key_secret .strip ())
215+ super (Auth , self ).__init__ (credentials_provider )
216+
217+
195218class AnonymousAuth (object ):
196219 """用于匿名访问。
197220
@@ -222,19 +245,16 @@ class StsAuth(object):
222245 """
223246 def __init__ (self , access_key_id , access_key_secret , security_token , auth_version = AUTH_VERSION_1 ):
224247 logger .debug ("Init StsAuth: access_key_id: {0}, access_key_secret: ******, security_token: ******" .format (access_key_id ))
225- self . __auth = make_auth (access_key_id , access_key_secret , auth_version )
226- self .__security_token = security_token
248+ credentials_provider = StaticCredentialsProvider (access_key_id , access_key_secret , security_token )
249+ self .__auth = ProviderAuthV2 ( credentials_provider ) if auth_version == AUTH_VERSION_2 else ProviderAuth ( credentials_provider )
227250
228251 def _sign_request (self , req , bucket_name , key ):
229- req .headers [OSS_SECURITY_TOKEN ] = self .__security_token
230252 self .__auth ._sign_request (req , bucket_name , key )
231253
232254 def _sign_url (self , req , bucket_name , key , expires ):
233- req .params ['security-token' ] = self .__security_token
234255 return self .__auth ._sign_url (req , bucket_name , key , expires )
235256
236257 def _sign_rtmp_url (self , url , bucket_name , channel_name , expires , params ):
237- params ['security-token' ] = self .__security_token
238258 return self .__auth ._sign_rtmp_url (url , bucket_name , channel_name , expires , params )
239259
240260
@@ -268,8 +288,9 @@ def v2_uri_encode(raw_text):
268288 'if-modified-since' ])
269289
270290
271- class AuthV2 (AuthBase ):
272- """签名版本2,与版本1的区别在:
291+ class ProviderAuthV2 (AuthBase ):
292+ """签名版本2,默认构造函数同父类AuthBase,需要传递credentials_provider
293+ 与版本1的区别在:
273294 1. 使用SHA256算法,具有更高的安全性
274295 2. 参数计算包含所有的HTTP查询参数
275296 """
@@ -283,20 +304,24 @@ def _sign_request(self, req, bucket_name, key, in_additional_headers=None):
283304 :param key: OSS文件名
284305 :param in_additional_headers: 加入签名计算的额外header列表
285306 """
307+ credentials = self .credentials_provider .get_credentials ()
308+ if credentials .get_security_token ():
309+ req .headers [OSS_SECURITY_TOKEN ] = credentials .get_security_token ()
310+
286311 if in_additional_headers is None :
287312 in_additional_headers = _DEFAULT_ADDITIONAL_HEADERS
288313
289314 additional_headers = self .__get_additional_headers (req , in_additional_headers )
290315
291316 req .headers ['date' ] = utils .http_date ()
292317
293- signature = self .__make_signature (req , bucket_name , key , additional_headers )
318+ signature = self .__make_signature (req , bucket_name , key , additional_headers , credentials )
294319
295320 if additional_headers :
296321 req .headers ['authorization' ] = "OSS2 AccessKeyId:{0},AdditionalHeaders:{1},Signature:{2}" \
297- .format (self . id , ';' .join (additional_headers ), signature )
322+ .format (credentials . get_access_key_id () , ';' .join (additional_headers ), signature )
298323 else :
299- req .headers ['authorization' ] = "OSS2 AccessKeyId:{0},Signature:{1}" .format (self . id , signature )
324+ req .headers ['authorization' ] = "OSS2 AccessKeyId:{0},Signature:{1}" .format (credentials . get_access_key_id () , signature )
300325
301326 def _sign_url (self , req , bucket_name , key , expires , in_additional_headers = None ):
302327 """返回一个签过名的URL
@@ -311,6 +336,9 @@ def _sign_url(self, req, bucket_name, key, expires, in_additional_headers=None):
311336
312337 :return: a signed URL
313338 """
339+ credentials = self .credentials_provider .get_credentials ()
340+ if credentials .get_security_token ():
341+ req .params ['security-token' ] = credentials .get_security_token ()
314342
315343 if in_additional_headers is None :
316344 in_additional_headers = set ()
@@ -323,23 +351,23 @@ def _sign_url(self, req, bucket_name, key, expires, in_additional_headers=None):
323351
324352 req .params ['x-oss-signature-version' ] = 'OSS2'
325353 req .params ['x-oss-expires' ] = str (expiration_time )
326- req .params ['x-oss-access-key-id' ] = self . id
354+ req .params ['x-oss-access-key-id' ] = credentials . get_access_key_id ()
327355
328- signature = self .__make_signature (req , bucket_name , key , additional_headers )
356+ signature = self .__make_signature (req , bucket_name , key , additional_headers , credentials )
329357
330358 req .params ['x-oss-signature' ] = signature
331359
332360 return req .url + '?' + '&' .join (_param_to_quoted_query (k , v ) for k , v in req .params .items ())
333361
334- def __make_signature (self , req , bucket_name , key , additional_headers ):
362+ def __make_signature (self , req , bucket_name , key , additional_headers , credentials ):
335363 if is_py2 :
336364 string_to_sign = self .__get_string_to_sign (req , bucket_name , key , additional_headers )
337365 else :
338366 string_to_sign = self .__get_bytes_to_sign (req , bucket_name , key , additional_headers )
339367
340368 logger .debug ('Make signature: string to be signed = {0}' .format (string_to_sign ))
341369
342- h = hmac .new (to_bytes (self . secret ), to_bytes (string_to_sign ), hashlib .sha256 )
370+ h = hmac .new (to_bytes (credentials . get_access_key_secret () ), to_bytes (string_to_sign ), hashlib .sha256 )
343371 return utils .b64encode_as_string (h .digest ())
344372
345373 def __get_additional_headers (self , req , in_additional_headers ):
@@ -427,7 +455,7 @@ def __get_bytes_to_sign(self, req, bucket_name, key, additional_header_list):
427455 canonicalized_oss_headers + \
428456 additional_headers + b'\n ' + \
429457 canonicalized_resource
430-
458+
431459 def __get_canonicalized_oss_headers_bytes (self , req , additional_headers ):
432460 """
433461 :param additional_headers: 小写的headers列表, 并且这些headers都不以'x-oss-'为前缀.
@@ -442,3 +470,13 @@ def __get_canonicalized_oss_headers_bytes(self, req, additional_headers):
442470 canon_headers .sort (key = lambda x : x [0 ])
443471
444472 return b'' .join (to_bytes (v [0 ]) + b':' + to_bytes (v [1 ]) + b'\n ' for v in canon_headers )
473+
474+
475+ class AuthV2 (ProviderAuthV2 ):
476+ """签名版本2,与版本1的区别在:
477+ 1. 使用SHA256算法,具有更高的安全性
478+ 2. 参数计算包含所有的HTTP查询参数
479+ """
480+ def __init__ (self , access_key_id , access_key_secret ):
481+ credentials_provider = StaticCredentialsProvider (access_key_id .strip (), access_key_secret .strip ())
482+ super (AuthV2 , self ).__init__ (credentials_provider )
0 commit comments