在Header中包含V1签名

更新时间:2025-01-24 09:13:37

OSS中,使用HTTP请求的Authorization Header来携带签名信息是进行身份验证的最常见方法。除了使用POST签名和URL签名之外,所有的OSS操作都需要通过Authorization Header来进行身份验证。本文介绍如何使用V1签名算法来在Header中包含签名。

重要

OSS支持更安全的V4签名算法,建议您使用V4签名。更多信息,请参见V4签名

SDK签名实现

OSS SDK已自动实现V1签名,您使用OSS SDK时无需关注签名问题。如果您想了解具体语言的签名实现,请参考OSS SDK的代码。OSS SDK签名实现的文件请参见下表。

SDK

签名实现

SDK

签名实现

Java

OSSV1Signer.java

PHP

SignerV1.php

Node.js

client.js

Browser.js

Python

auth.py

.Net

OssRequestSigner.cs

Android

OSSUtils.java

Go

v1.go

iOS

OSSModel.m

C++

SignerV1.cc

C

oss_auth.c

Ruby

util.rb

Authorization字段计算的方法

计算方法

Authorization = "OSS " + AccessKeyId + ":" + Signature
Signature = base64(hmac-sha1(AccessKeySecret,
            VERB + "\n"
            + Content-MD5 + "\n" 
            + Content-Type + "\n" 
            + Date + "\n" 
            + CanonicalizedOSSHeaders
            + CanonicalizedResource))

参数说明

参数

类型

是否必选

示例值

说明

参数

类型

是否必选

示例值

说明

AccessKeyId

字符串

LTAI********************

填写当前账号的访问密钥AccessKey,包括AccessKey IDAccessKey Secret。

AccessKeySecret

字符串

Q0Ye**************************

x-oss-security-token

字符串

CAIS********************************

STS安全令牌。仅当使用STS构造Header签名时,才需要设置此参数。关于如何获取Security-Token的具体操作,请参见AssumeRole - 获取扮演角色的临时身份凭证

VERB

枚举值

PUT

HTTP请求的Method,包含PUT、GET、POST、HEAD、DELETE、OPTIONS等。

\n

字符串

\n

换行符。

Content-MD5

字符串

eB5eJF1ptWaXm4bijSPyxw==

请求内容数据的MD5值,对消息内容(不包括头部)计算MD5值获得128比特位数字,对该数字进行base64编码得出。更多信息,请参见RFC2616 Content-MD5

该请求头可用于消息合法性的检查(消息内容是否与发送时一致),也可以为空。

关于Content-MD5的计算方法,请参见Content-MD5的计算方法

Content-Type

字符串

application/octet-stream

请求内容的类型,也可以为空。

说明

如果生成签名时没有设置Content-Type,则后续使用签名上传文件时也无需设置该参数。

Date

字符串

Sun, 22 Nov 2015 08:16:38 GMT

此次操作的时间,Date必须为GMT格式,且不能为空。该值取自请求头的Date字段或者x-oss-date字段。当这两个字段同时存在时,以x-oss-date为准。

重要

如果请求中的Date时间和OSS服务器的当前时间差15分钟以上,OSS服务器将拒绝该请求,并返回HTTP 403错误。

CanonicalizedOSSHeaders

字符串

x-oss-meta-a:a\nx-oss-meta-b:b\nx-oss-meta-c:c\n

x-oss-为前缀的HTTP Header的字典序排列,可以为空。

  • 如果设置CanonicalizedOSSHeaders为空,则无需在最后添加分隔符\n

  • 如果只有一个CanonicalizedOSSHeaders,则需要在最后添加分隔符\n,例如x-oss-meta-a\n

  • 如果有多个CanonicalizedOSSHeaders,则需要在每一个CanonicalizedOSSHeaders之后添加分隔符\n,例如x-oss-meta-a:a\nx-oss-meta-b:b\nx-oss-meta-c:c\n

关于CanonicalizedOSSHeaders的构建方法,请参见构建CanonicalizedOSSHeaders的方法

CanonicalizedResource

字符串

examplebucket

您希望访问的OSS资源,不能为空。

关于CanonicalizedResource的构建方法,请参见构建CanonicalizedResource的方法

签名示例

  • 示例1(包含所有参数)

    请求

    签名字符串计算公式

    签名字符串

    请求

    签名字符串计算公式

    签名字符串

    PUT /nelson HTTP/1.0 Content-MD5: eB5eJF1ptWaXm4bijSPyxw== Content-Type: text/html Date: Wed, 28 Dec 2022 10:27:41 GMT Host: examplebucket.oss-cn-hangzhou.aliyuncs.com x-oss-meta-author: alice x-oss-meta-magic: abracadabra

    Signature = base64(hmac-sha1(AccessKeySecret,VERB + “\n” + Content-MD5 + “\n”+ Content-Type + “\n” + Date + “\n” + CanonicalizedOSSHeaders+ CanonicalizedResource))

    PUT\n eB5eJF1ptWaXm4bijSPyxw==\n text/html\n Wed, 28 Dec 2022 10:27:41 GMT\n x-oss-meta-magic:abracadabra\nx-oss-meta-author:alice\n/examplebucket/nelson

    假设AccessKey IDLTAI********************,AccessKey SecretQ0Ye**************************,此处以Python为例介绍计算签名(Signature)的方法。

    import hmac
    import hashlib
    import base64
    
    h = hmac.new("Q0Ye**************************".encode('utf-8'),
                 "PUT\nODBGOERFMDMzQTczRUY3NUE3NzA5QzdFNUYzMDQxNEM\ntext/html\nWed, 28 Dec 2022 10:27:41 GMT\nx-oss-meta-magic:abracadabra\nx-oss-meta-author:alice\n/oss-example/nelson".encode('utf-8'), hashlib.sha1)
    signature =  base64.encodebytes(h.digest())
    print(signature)

    签名(Signature)计算结果为J9Nl************************,结合Authorization头的结构组成,需要发送的消息体如下。

    PUT /nelson HTTP/1.0
    Authorization:OSS LTAI********************:J9Nl************************
    Content-Md5: eB5eJF1ptWaXm4bijSPyxw==
    Content-Type: text/html
    Date: Wed, 28 Dec 2022 10:27:41 GMT
    Host: oss-example.oss-cn-hangzhou.aliyuncs.com
    x-oss-meta-author: alice
    x-oss-meta-magic: abracadabra
  • 示例2(不包含可选参数Content-MD5以及Content-Type)

    请求

    签名字符串计算公式

    签名字符串

    请求

    签名字符串计算公式

    签名字符串

    PUT /nelson HTTP/1.0 Date: Wed, 28 Dec 2022 09:56:32 GMT Host: examplebucket.oss-cn-hangzhou.aliyuncs.com x-oss-meta-author: alice x-oss-meta-magic: abracadabra

    Signature = base64(hmac-sha1(AccessKeySecret,VERB + “\n” + “\n”+ “\n” + Date + “\n” + CanonicalizedOSSHeaders+ CanonicalizedResource))

    PUT\n\n\nWed, 28 Dec 2022 09:56:32 GMT\n x-oss-meta-magic:abracadabra\nx-oss-meta-author:alice\n/examplebucket/nelson

    假设AccessKey IDLTAI********************,AccessKey SecretKZo1**************************,此处以Python为例介绍计算签名(Signature)的方法。

    import hmac
    import hashlib
    import base64
    
    h = hmac.new("KZo1**************************".encode('utf-8'),
                 "PUT\n\n\nWed, 28 Dec 2022 09:56:32 GMT\nx-oss-meta-magic:abracadabra\nx-oss-meta-author:alice\n/oss-example/nelson".encode('utf-8'), hashlib.sha1)
    signature =  base64.encodebytes(h.digest())
    print(signature)

    签名(Signature)计算结果为Mhb1************************,结合Authorization头的结构组成,需要发送的消息体如下。

    PUT /nelson HTTP/1.0
    Authorization:OSS LTAI********************:Mhb1************************
    Date: Wed, 28 Dec 2022 09:56:32 GMT
    Host: oss-example.oss-cn-hangzhou.aliyuncs.com
    x-oss-meta-author: alice
    x-oss-meta-magic: abracadabra

相关说明

  • 如果传入的AccessKey ID不存在或未激活,则返回403 Forbidden错误,错误码为InvalidAccessKeyId;如果AccessKey ID已激活,但OSS判断用户的请求发生签名错误,则返回403 Forbidden错误,并在返回的response中显示正确的用于验证加密的签名字符串。您可以根据OSSresponse来检查自己的签名字符串是否正确。

    返回示例如下:

    <?xml version="1.0" ?>
    <Error>
     <Code>
         SignatureDoesNotMatch
     </Code>
     <Message>
         The request signature we calculated does not match the signature you provided. Check your key and signing method.
     </Message>
     <StringToSignBytes>
         47 45 54 0a 0a 0a 57 65 64 2c 20 31 31 20 4d 61 79 20 32 30 31 31 20 30 37 3a 35 39 3a 32 35 20 47 4d 54 0a 2f 75 73 72 65 61 6c 74 65 73 74 3f 61 63 6c
     </StringToSignBytes>
     <RequestId>
         1E446260FF9B****
     </RequestId>
     <HostId>
         oss-cn-hangzhou.aliyuncs.***
     </HostId>
     <SignatureProvided>
         y5H7yzPsA/tP4+0tH1HHvPEwUv8=
     </SignatureProvided>
     <StringToSign>
         GET
    Wed, 11 May 2011 07:59:25 GMT
    /examplebucket?acl
     </StringToSign>
     <OSSAccessKeyId>
         AKIAIVAKMSMOY7VO****
     </OSSAccessKeyId>
    </Error>
  • 如果用户请求头中Authorization值的格式不对,则返回400 Bad Request错误,错误码为InvalidArgument。

  • OSS所有的请求都必须使用HTTP 1.1协议规定的GMT时间格式。其中,日期的格式为:

    date1 = 2DIGIT SP month SP 4DIGIT; day month year (e.g., 02 Jun 1982)
    说明

    上述日期格式中day所占位数为2DIGIT,因此Jun 22 Jun 1982以及2-Jun-1982均为非法日期格式。

    • 如果签名验证时,Authorization头中没有传入Date,或者传入的格式不正确,则返回403 Forbidden错误,错误码为AccessDenied。

    • 传入请求的时间必须在OSS服务器当前时间之后的15分钟以内,否则返回403 Forbidden错误,错误码为RequestTimeTooSkewed。

构建CanonicalizedOSSHeaders的方法

所有以x-oss-为前缀的HTTP Header被称为CanonicalizedOSSHeaders,构建方法如下:

  1. 将所有以x-oss-为前缀的HTTP请求头的名称转换为小写的形式,例如X-OSS-Meta-Name: TaoBao转换为x-oss-meta-name: TaoBao

  2. 如果以从STS服务获取的临时访问凭证发送请求时,您还需要将获得的security-token值以x-oss-security-token:security-token的形式加入到签名字符串中。

    说明

    关于搭建STS服务的具体操作,请参见使用STS临时访问凭证访问OSS。您可以通过调用STS服务的AssumeRole接口或者使用各语言STS SDK来获取临时访问凭证。临时访问凭证包括临时访问密钥(AccessKey IDAccessKey Secret)和安全令牌(SecurityToken)。各语言STS SDK来获取临时访问凭证。临时访问凭证包括临时访问密钥(AccessKey IDAccessKey Secret)和安全令牌(SecurityToken)。

  3. 将获取的所有HTTP请求头按照名称的字典序进行升序排列。

  4. 删除请求头和内容之间分隔符两端出现的任何空格。例如x-oss-meta-name: TaoBao转换为x-oss-meta-name:TaoBao

  5. 将每一个请求头和内容使用分隔符\n分隔拼成CanonicalizedOSSHeaders。

构建CanonicalizedResource的方法

发送请求中希望访问的OSS目标资源被称为CanonicalizedResource,构建方法如下:

  • 如果既有BucketName也有ObjectName,则CanonicalizedResource格式为/BucketName/ObjectName

  • 如果仅有BucketName而没有ObjectName,则CanonicalizedResource格式为/BucketName/

  • 如果既没有BucketName也没有ObjectName,则CanonicalizedResource为正斜线(/)。

  • 如果请求的资源包括子资源(SubResource),则所有的子资源需按照字典序升序排列,并以&为分隔符生成子资源字符串。在CanonicalizedResource字符串尾添加?和子资源字符串。此时的CanonicalizedResource/BucketName/ObjectName?acl&uploadId=UploadId

    OSS支持以下四种类型的子资源:

    • 资源标识,例如acl、uploads、location、cors、logging、website、referer、lifecycle、delete、append、tagging、objectMeta、uploadId、partNumber、security-token、position、img、style、styleName、replication、replicationProgress、replicationLocation、cname、bucketInfo、comp、qos、live、status、vod、startTime、endTime、symlink、x-oss-process、callback、callback-var等。更多信息,请参见关于Bucket的操作关于Object的操作

      重要

      资源标识严格区分大小写。

    • 指定返回Header字段,例如response-content-language、response-expires、response-cache-control、response-content-disposition、response-content-encoding等。更多信息,请参见GetObject

    • 图片处理操作方式,例如x-oss-process。更多信息,请参见图片处理

    • x-oss-ac-*开头的访问控制字段,例如x-oss-ac-source-ip、x-oss-ac-subnet-mask、x-oss-ac-vpc-id、x-oss-ac-forward-allow。更多信息,请参见签名版本1

      说明

      使用包含x-oss-ac-source-ip参数的CanonicalizedResource生成签名后,请从需要发送的消息query参数中移除x-oss-ac-source-ip,以保护IP地址信息安全。

计算签名头规则

  • 签名的字符串必须为UTF-8格式。含有中文字符的签名字符串必须先进行UTF-8编码,再与AccessKeySecret计算最终签名。

  • 签名的方法用RFC 2104中定义的HMAC-SHA1方法,其中Key指的是AccessKey Secret。

  • Content-TypeContent-MD5在请求中不是必须的,如果请求需要签名验证,空值请以换行符\n代替。

  • 在所有非HTTP标准定义的Header中,只有以x-oss-开头的Header需要加入签名字符串(例如签名示例中的x-oss-meta-magic则需要加入签名字符串);其他非HTTP标准Header将被OSS忽略。

    说明

    x-oss-开头的Header在签名验证前需要符合以下规范:

    • Header的名称需要转为小写。

    • Header按字典序升序排序。

    • 分割Headernamevalue之间的冒号前后不能有空格。

    • 每个Header之后都要有一个换行符“\n”,如果没有Header,则设置CanonicalizedOSSHeaders为空。

Content-MD5的计算方法

以消息内容“0123456789”为例,以下详细说明正确及错误计算该字符串的Content-MD5的方法。

  • 正确计算示例

    1. 先计算MD5加密的二进制数组(128位)。

    2. 对该二进制数组进行base64编码(而不是对32位字符串编码)。

    Python为例:

    >>> import base64,hashlib
    >>> hash = hashlib.md5()
    >>> hash.update("0123456789")   #在Python 3中此处需要改为hash.update(b"0123456789")。
    >>> base64.b64encode(hash.digest())
    'eB5eJF1ptWaXm4bijSPyxw=='

    hash.digest(),计算出二进制数组(128位)。

    >>> hash.digest()
    'x\x1e^$]i\xb5f\x97\x9b\x86\xe2\x8d#\xf2\xc7'
  • 错误计算示例

    说明

    常见错误是直接对计算出的32位字符串进行base64编码。

    #hash.hexdigest(),计算得到可见的32位字符串编码。
    >>> hash.hexdigest()
    '781e5e245d69b566979b86e28d23f2c7'
    # 错误的MD5值进行base64编码后的结果。
    >>> base64.b64encode(hash.hexdigest())
    'NzgxZTVlMjQ1ZDY5YjU2Njk3OWI4NmUyOGQyM2YyYzc='
  • 本页导读 (1)
  • SDK签名实现
  • Authorization字段计算的方法
  • 计算方法
  • 参数说明
  • 签名示例
  • 相关说明
  • 构建CanonicalizedOSSHeaders的方法
  • 构建CanonicalizedResource的方法
  • 计算签名头规则
  • Content-MD5的计算方法