更新时间:2025-08-18 15:49:30
对于鉴权请求,除非您使用SDK,否则需要自行编写代码计算签名,在请求中提供认证信息。签名计算过程相对复杂,建议您优先使用 SDKs。
本节以一个示例请求说明如何计算签名。假设您要调用API GetBucket,并列出bucket test-authentication中以"OS"为前缀的文件,请求如下:
示例请求
GET /?prefix=OS HTTP/1.1
Host: test-authentication.s3-cn-north-1.wcsapi.com
x-wos-date:20201103T104419Z
Authorization: <Authorization>
import sys, os, base64, datetime, hashlib, hmac
import requests
# ************* 请求相关参数 *************
# 下述代码展示如何在请求头中包含认证信息
# 以API GetBucket为例
# GET /?prefix=OS
# Host: test-authentication.s3-cn-north-1.wcsapi.com
service = 'wos'
host = 'test-authentication.s3-cn-north-1.wcsapi.com'
region = 'cn-north-1'
endpoint = 'http://test-authentication.s3-cn-north-1.wcsapi.com'
request_parameters = 'prefix=OS'
# Key 派生函数
def sign(key, msg):
return hmac.new(key, msg.encode('utf-8'), hashlib.sha256).digest()
# 派生SigningKey函数
def getSignatureKey(key, dateStamp, regionName, serviceName):
kDate = sign(('WOS' + key).encode('utf-8'), dateStamp)
kRegion = sign(kDate, regionName)
kService = sign(kRegion, serviceName)
kSigning = sign(kService, 'wos_request')
return kSigning
# Access Key和Access Key Secret。您也可以从环境变量或配置文件读取。
access_key = 'LqswcPGFYA06V0fQ2HtgVRR3Wi5fzpR******'
secret_key = 'B2UZV6uwULVnosYQxORTYSdbTTAJVptWvDoV0fLENgA3ERPc8UxYfvTigS******'
if access_key is None or secret_key is None:
print('No access key is available.')
sys.exit()
# 生成header和凭证字符串所需时间
t = datetime.datetime.utcnow()
wosdate = t.strftime('%Y%m%dT%H%M%SZ')
print('wosdate is: ' + wosdate)
datestamp = t.strftime('%Y%m%d') # 日期(不含时间),用于凭证范围
# ************* 步骤1:创建规范化请求 *************
# Step 1: 定义HTTP方法
method = 'GET'
# Step 2: 创建规范化URI
# GetBucket操作无需path,所以用'/'
canonical_uri = '/'
# Step 3: 创建规范化查询字符串
# 查询参数应进行URL编码并按照名称排序
canonical_querystring = request_parameters
# Step 4: 创建规范化请求头
# 头部名需小写、去除空格并按编码排序,且末尾要加\n
canonical_headers = 'host:' + host + '\n' + 'x-wos-date:' + wosdate + '\n'
# Step 5: 创建已签名头列表,英文分号分隔并按字母顺序
signed_headers = 'host;x-wos-date'
# Step 6: 创建payload哈希(body内容哈希),GET请求body为空字符串
payload_hash = hashlib.sha256(('').encode('utf-8')).hexdigest()
# Step 7: 拼接形成规范化请求字符串
canonical_request = method + '\n' + canonical_uri + '\n' + canonical_querystring + '\n' + canonical_headers + '\n' + signed_headers + '\n' + payload_hash
# ************* 步骤2:创建待签名字符串*************
algorithm = 'WOS-HMAC-SHA256'
credential_scope = datestamp + '/' + region + '/' + service + '/' + 'wos_request'
string_to_sign = algorithm + '\n' + wosdate + '\n' + credential_scope + '\n' + hashlib.sha256(canonical_request.encode('utf-8')).hexdigest()
# ************* 步骤3:计算签名 *************
# 通过上面的函数获得签名密钥
signing_key = getSignatureKey(secret_key, datestamp, region, service)
# 用签名密钥对待签名字符串做hash,得到签名
signature = hmac.new(signing_key, (string_to_sign).encode('utf-8'), hashlib.sha256).hexdigest()
print(signature)
# ************* 步骤4:将签名信息加入到请求头 *************
# 创建authorization头并加入请求
authorization_header = algorithm + ' ' + 'Credential=' + access_key + '/' + credential_scope + ', ' + 'SignedHeaders=' + signed_headers + ', ' + 'Signature=' + signature
headers = {'x-wos-date':wosdate, 'Authorization':authorization_header}
# ************* 发送请求 *************
request_url = endpoint + '?' + canonical_querystring
print('\nBEGIN REQUEST++++++++++++++++++++++++++++++++++++')
print('Request URL = ' + request_url)
r = requests.get(request_url, headers=headers)
print('\nRESPONSE++++++++++++++++++++++++++++++++++++')
print('Response code: %d\n' % r.status_code)
print(r.text)