Skip to content

Commit

Permalink
add host to the string to sign (#172)
Browse files Browse the repository at this point in the history
* support redirect config

* set allow_redirects default value to false

* add host to str_to_sign

* add host to the string to sign

* add host to the string to sign

* add host to the string to sign

* add host to the string to sign

* url = u"{scheme}://{bucket}.{endpoint}/{

* add host to the string to sign

* add host to the string to sign

Co-authored-by: yuniszhang <[email protected]>
  • Loading branch information
zhy1985555 and yuniszhang authored Aug 24, 2021
1 parent c354d38 commit 20d9e94
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 8 deletions.
26 changes: 25 additions & 1 deletion qcloud_cos/cos_auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,19 @@ def filter_headers(data):

class CosS3Auth(AuthBase):

def __init__(self, conf, key=None, params={}, expire=10000):
def __init__(self, conf, key=None, params={}, expire=10000, sign_host=None):
self._secret_id = conf._secret_id
self._secret_key = conf._secret_key
self._anonymous = conf._anonymous
self._expire = expire
self._params = params

# 如果API指定了是否签名host,则以具体API为准,如果未指定则以配置为准
if sign_host is not None:
self._sign_host = bool(sign_host)
else:
self._sign_host = conf._sign_host

if key:
key = to_unicode(key)
if key[0] == u'/':
Expand All @@ -55,6 +62,23 @@ def __call__(self, r):
path = self._path
uri_params = self._params
headers = filter_headers(r.headers)

# 如果headers中不包含host头域,则从url中提取host,并且加入签名计算
if self._sign_host:

# 判断headers中是否包含host头域
contain_host = False
for i in headers:
if str.lower(i) == "host": # 兼容host/Host/HOST等
contain_host = True
break

# 从url中提取host
if not contain_host:
url_parsed = urlparse(r.url)
if url_parsed.hostname is not None:
headers["host"] = url_parsed.hostname

# reserved keywords in headers urlencode are -_.~, notice that / should be encoded and space should not be encoded to plus sign(+)
headers = dict([(quote(to_bytes(to_str(k)), '-_.~').lower(), quote(to_bytes(to_str(v)), '-_.~')) for k, v in
headers.items()]) # headers中的key转换为小写,value进行encode
Expand Down
19 changes: 12 additions & 7 deletions qcloud_cos/cos_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ class CosConfig(object):
def __init__(self, Appid=None, Region=None, SecretId=None, SecretKey=None, Token=None, Scheme=None, Timeout=None,
Access_id=None, Access_key=None, Secret_id=None, Secret_key=None, Endpoint=None, IP=None, Port=None,
Anonymous=None, UA=None, Proxies=None, Domain=None, ServiceDomain=None, PoolConnections=10,
PoolMaxSize=10, AllowRedirects=False):
PoolMaxSize=10, AllowRedirects=False, SignHost=True):
"""初始化,保存用户的信息
:param Appid(string): 用户APPID.
Expand All @@ -64,6 +64,7 @@ def __init__(self, Appid=None, Region=None, SecretId=None, SecretKey=None, Token
:param PoolConnections(int): 连接池个数
:param PoolMaxSize(int): 连接池中最大连接数
:param AllowRedirects(bool): 是否重定向
:param SignHost(bool): 是否将host算入签名
"""
self._appid = to_unicode(Appid)
self._token = to_unicode(Token)
Expand All @@ -80,6 +81,7 @@ def __init__(self, Appid=None, Region=None, SecretId=None, SecretKey=None, Token
self._pool_connections = PoolConnections
self._pool_maxsize = PoolMaxSize
self._allow_redirects = AllowRedirects
self._sign_host = SignHost

if self._domain is None:
self._endpoint = format_endpoint(Endpoint, Region)
Expand Down Expand Up @@ -201,7 +203,7 @@ def get_conf(self):
"""获取配置"""
return self._conf

def get_auth(self, Method, Bucket, Key, Expired=300, Headers={}, Params={}):
def get_auth(self, Method, Bucket, Key, Expired=300, Headers={}, Params={}, SignHost=None):
"""获取签名
:param Method(string): http method,如'PUT','GET'.
Expand All @@ -210,6 +212,7 @@ def get_auth(self, Method, Bucket, Key, Expired=300, Headers={}, Params={}):
:param Expired(int): 签名有效时间,单位为s.
:param headers(dict): 签名中的http headers.
:param params(dict): 签名中的http params.
:param SignHost(bool): 是否将host算入签名.
:return (string): 计算出的V5签名.
.. code-block:: python
Expand All @@ -229,7 +232,7 @@ def get_auth(self, Method, Bucket, Key, Expired=300, Headers={}, Params={}):
"""
url = self._conf.uri(bucket=Bucket, path=Key)
r = Request(Method, url, headers=Headers, params=Params)
auth = CosS3Auth(self._conf, Key, Params, Expired)
auth = CosS3Auth(self._conf, Key, Params, Expired, SignHost)
return auth(r).headers['Authorization']

def send_request(self, method, url, bucket, timeout=30, cos_request=True, **kwargs):
Expand Down Expand Up @@ -491,7 +494,7 @@ def get_object_sensitive_content_recognition(self, Bucket, Key, DetectType, Inte

return data

def get_presigned_url(self, Bucket, Key, Method, Expired=300, Params={}, Headers={}):
def get_presigned_url(self, Bucket, Key, Method, Expired=300, Params={}, Headers={}, SignHost=None):
"""生成预签名的url
:param Bucket(string): 存储桶名称.
Expand All @@ -500,6 +503,7 @@ def get_presigned_url(self, Bucket, Key, Method, Expired=300, Params={}, Headers
:param Expired(int): 签名过期时间.
:param Params(dict): 签入签名的参数
:param Headers(dict): 签入签名的头部
:param SignHost(bool): 是否将host算入签名.
:return(string): 预先签名的URL.
.. code-block:: python
Expand All @@ -514,21 +518,22 @@ def get_presigned_url(self, Bucket, Key, Method, Expired=300, Params={}, Headers
)
"""
url = self._conf.uri(bucket=Bucket, path=Key)
sign = self.get_auth(Method=Method, Bucket=Bucket, Key=Key, Expired=Expired, Headers=Headers, Params=Params)
sign = self.get_auth(Method=Method, Bucket=Bucket, Key=Key, Expired=Expired, Headers=Headers, Params=Params, SignHost=SignHost)
sign = urlencode(dict([item.split('=', 1) for item in sign.split('&')]))
url = url + '?' + sign
if Params:
url = url + '&' + urlencode(Params)
return url

def get_presigned_download_url(self, Bucket, Key, Expired=300, Params={}, Headers={}):
def get_presigned_download_url(self, Bucket, Key, Expired=300, Params={}, Headers={}, SignHost=None):
"""生成预签名的下载url
:param Bucket(string): 存储桶名称.
:param Key(string): COS路径.
:param Expired(int): 签名过期时间.
:param Params(dict): 签入签名的参数
:param Headers(dict): 签入签名的头部
:param SignHost(bool): 是否将host算入签名.
:return(string): 预先签名的下载URL.
.. code-block:: python
Expand All @@ -541,7 +546,7 @@ def get_presigned_download_url(self, Bucket, Key, Expired=300, Params={}, Header
Key='test.txt'
)
"""
return self.get_presigned_url(Bucket, Key, 'GET', Expired, Params, Headers)
return self.get_presigned_url(Bucket, Key, 'GET', Expired, Params, Headers, SignHost)

def get_object_url(self, Bucket, Key):
"""生成对象访问的url
Expand Down

0 comments on commit 20d9e94

Please sign in to comment.