edit-icon download-icon

Add a signature to the header

最終更新日: Dec 10, 2018

Authorization ヘッダーを追加して、HTTP リクエストに署名情報を含めることができます。これにより、そのメッセージが権限付与済みであることが示されます。

Authorization フィールドの計算

  1. Authorization = "OSS " + AccessKeyId + ":" + Signature
  2. Signature = base64(hmac-sha1(AccessKeySecret,
  3. VERB + "\n"
  4. + Content-MD5 + "\n"
  5. + Content-Type + "\n"
  6. + Date + "\n"
  7. + CanonicalizedOSSHeaders
  8. + CanonicalizedResource))
  • AccessKeySecret は、署名に必要なキーを示します。
  • VERB は、HTTP リクエストメソッド (PUT、GET、POST、HEAD、DELETE) を示します。
  • \nは改行です。
  • Content-MD5 は、リクエストコンテンツデータの MD5 の値を示します。メッセージの内容(ヘッダーを除く)は、128ビットの数値であるMD5値を取得するために計算されます。 この番号はBase64でContent-MD5値にエンコードされます。 要求ヘッダーを使用して、メッセージの有効性をチェックすることができます。つまり、メッセージの内容が “eB5eJF1ptWaXm4bijSPyxw ==”などの送信されたコンテンツと一致するかどうかを確認できます。詳細については、『RFC2616』を参照してください。
  • Content-Type は、リクエストコンテンツのタイプを示します。”application/octet-stream” のようなものである。 それは空であるかもしれません。
  • DATE は、操作の日時を示します。HTTP1.1 でサポートされている GMT 形式である必要があります。
  • CanonicalizedOSSHeaders は、プレフィックスが “x-oss-“ である HTTP ヘッダーのアセンブリを示します。
  • CanonicalizedResource は、ユーザーがアクセスしようとしている OSS リソースを示します。

これらのうち、DATE と CanonicalizedResource は、値を空白にすることができません。リクエストの DATE の値と OSS サーバーの時刻の差が 15 分を超えていると、OSS サーバーはサービスを拒否して HTTP 403 エラーを返します。

CanonicalizedOSSHeaders の作成

プレフィックスが “x-oss-“ であるすべての HTTP ヘッダーを CanonicalizedOSSHeaders と呼びます。CanonicalizedOSSHeaders を作成する方法を以下に示します。

  1. プレフィックスが x-oss- であるすべての HTTP リクエストヘッダーの名前を小文字に変換します。たとえば、X-OSS-Meta-Name: TaoBaox-oss-meta-name: TaoBao に変換します。
  2. 前の手順で得られたすべての HTTP リクエストヘッダーを辞書式順序の昇順で並べ替えます。
  3. RFC2616』の第 4.2 章に従って、同じ名前のリクエストヘッダーを結合します (2 つの値をコンマ (,) で区切ります)。たとえば、”x-oss-meta-name” というリクエストヘッダーが 2 つあり、値が “TaoBao” と “Alipay” である場合、値を結合すると x-oss-meta-name:TaoBao,Alipay になります。
  4. リクエストのヘッダーとコンテンツの間にある区切り記号の両側のスペースを削除します。たとえば、x-oss-meta-name: TaoBao,Alipayx-oss-meta-name:TaoBao,Alipay に変換します。
  5. すべてのヘッダーとコンテンツのペアを、区切り記号に “\n” を使用して区切ります。これで、CanonicalizedOSSHeaders が完成します。

注意

  • CanonicalizedOSSHeaders が null の場合、末尾に \n を追加する必要はありません。
  • ヘッダーが1つだけの場合、x-oss-meta-a \n のようにする必要があります。 最後に \n に注意してください。
  • 複数のヘッダーがある場合、x-oss-meta-a:a\nx-oss-meta-b:b\nx-oss-meta-c:c\n のようになります。 最後に\nに注意してください。

CanonicalizedResource の作成

ユーザーが送信するリクエストに指定されているターゲット OSS リソースを CanonicalizedResource と呼びます。CanonicalizedResource を作成する方法を以下に示します。

  1. CanonicalizedResource を空白の文字列 (“”) として設定します。
  2. アクセスする OSS リソースを ‘/BucketName/ObjectName’の形式で追加します。 (ObjectName が存在しない場合、CanonicalizedResourceは /BucketName/です。 BucketNameが存在しない場合、CanonicalizedResource は “/“です。
  3. リクエストするリソースにサブリソースが含まれている場合は、すべてのサブリソースを辞書式順序の昇順で並べ替えて、区切り記号に & を使用して区切り、サブリソース文字列を生成します。そのサブリソース文字列を、”?” と共に CanonicalizedResource 文字列の末尾に追加します。この場合、CanonicalizedResource は、たとえば /BucketName/ObjectName?acl &uploadId=UploadId のようになります。
  4. ユーザーリクエストでクエリ文字列(QueryString、HTTP リクエストパラメータとも呼ばれます)が指定されている場合は、これらのクエリ文字列をソートし、辞書順の昇順で値を要求し、セパレータ ‘&’を使用してクエリ文字列と要求値を分離し、パラメータに基づいてそれらを CanonicalizedResource に追加します。この場合、CanonicalizedResource は次のようになります。/BucketName/ObjectName?acl&response-content-type=ContentType&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, response-content-type, response-content-language, response-expires, response-cache-control, response-content-disposition および response-content-encoding。
  • サブリソースには次の 3 種類があります。

署名ヘッダーの計算のルール

  1. 署名に使用する文字列は UTF-8 形式である必要があります。漢字を含む署名文字列に対しては、UTF-8 エンコーディングを実行する必要があります。その後、Access Key Secretと共に使用して最終的な署名を計算できます。
  2. 署名方法には、RFC 2104 で定義されている HMAC-SHA1 方式が採用されています (Key はAccess Key Secretです)。
  3. リクエストの Content-Type と Content-MD5 は省略可能です。署名の検証が必要な場合は null 値を改行 “\n” に置き換えます。
  4. すべての非標準 HTTP ヘッダーのうち、署名文字列が必要なのは、”x-oss-“ で始まるヘッダーだけです。その他の非標準 HTTP ヘッダー (上の例の x-oss-magic など) は、OSS では無視されます。
  5. “x-oss-“ で始まるヘッダーを署名の検証に使用するには、次の仕様に準拠している必要があります。
    • ヘッダー名が小文字に変更されている。
    • ヘッダーが辞書式順序の昇順で並べ替えられている。
    • ヘッダーの名前と値を区切るコロンの前後にスペースがない。
    • 各ヘッダーの後に改行 “\n” がある。ヘッダーがない場合、CanonicalizedOSSHeaders は null に設定されます。

署名の例

AccessId が “44CF9590006BF252F707” で、 Access Key Secret が “OtxrzxIsfpFjA7SwPzILwy8Bw21TLhquhboDYROV” であるとすると、署名を追加する方法は次のようになります。

リクエスト 署名文字列計算式 署名文字列
PUT /nelson HTTP/1.0
Content-MD5: eB5eJF1ptWaXm4bijSPyxw==
Content-Type: text/html
Date: Thu, 17 Nov 2005 18:49:58 GMT
Host: oss-example.oss-cn-hangzhou.aliyuncs.com
X-OSS-Meta-Author: foo@bar.com
X-OSS-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
Thu, 17 Nov 2005 18:49:58 GMT\n
x-oss-magic:abracadabra\nx-oss-meta-author:foo@bar.com\n
/oss-example/nelson”

署名の計算方法は次のとおりです。

Python コードの例

  1. import base64
  2. import hmac
  3. import sha
  4. h = hmac.new("OtxrzxIsfpFjA7SwPzILwy8Bw21TLhquhboDYROV",
  5. "PUT\neB5eJF1ptWaXm4bijSPyxw==\ntext/html\nThu, 17 Nov 2005 18:49:58 GMT\nx-oss-magic:abracadabra\nx-oss-meta-author:foo@bar.com\n/oss-example/nelson", sha)
  6. base64.encodestring(h.digest()).strip()
  7. print("Signature: %s" % Signature)

計算される署名は 26NBxoKdsyly4EDv6inkoDft/yA= です。式Authorization = “OSS” + AccessKeyID + “:” + Signatureによれば、許可の値はOSS 44CF9590006BF252F707:26NBxoKdsyly4EDv6inkoDft/yA= です。この値は、送信されるメッセージを形成するために認証ヘッダーとともに追加されます。

  1. PUT /nelson HTTP/1.0
  2. Authorization:OSS 44CF9590006BF252F707:26NBxoKdsyly4EDv6inkoDft/yA=
  3. Content-Md5: eB5eJF1ptWaXm4bijSPyxw==
  4. Content-Type: text/html
  5. Date: Thu, 17 Nov 2005 18:49:58 GMT
  6. Host: oss-example.oss-cn-hangzhou.aliyuncs.com
  7. X-OSS-Meta-Author: foo@bar.com
  8. X-OSS-Magic: abracadabra

詳細分析

  1. AccessID が受信されない場合や、受信した AccessID がアクティブでない場合は、エラー 403 Forbidden が返されます。エラーコードは InvalidAccessKeyId です。
  2. ユーザーリクエストヘッダーの Authorization の値が無効である場合は、エラー 400 Bad Request が返されます。エラーコードは InvalidArgument です。
  3. OSS のすべてのリクエストで、HTTP 1.1 プロトコルによって規定されている GMT 時刻形式を使用する必要があります。次の 3 つの日付形式を使用できます。date1 = 2DIGIT SP month SP 4DIGIT; day month year (例: 02 Jun 1982)上の 3 つの日付形式では、”day” が “2 DIGIT” になっています。したがって、”Jun 2”、”2 Jun 1982”、”2-Jun-82” はすべて無効な日付形式になります。
  4. Date がヘッダーに入力されていない場合や、署名の検証で形式が正しくないと判断された場合は、エラー 403 Forbidden が返されます。エラーコードは AccessDenied です。
  5. リクエストは、OSS サーバーの現在の時刻に基づいて 15 分以内に入力する必要があります。そうしないと、エラー 403 Forbidden が返されます。エラーコードは RequestTimeTooSkewed です。
  6. AccessID はアクティブだが、ユーザーリクエストの署名が正しくないと判断された場合は、エラー 403 Forbidden が返され、検証と暗号化のための正しい署名文字列がユーザーに応答メッセージで返されます。この OSS の応答に基づいて、署名文字列が正しいかどうかを確認できます。戻り値の例:
    1. <?xml version="1.0" ?>
    2. <Error>
    3. <Code>
    4. SignatureDoesNotMatch
    5. </Code>
    6. <Message>
    7. The request signature we calculated does not match the signature you provided. Check your key and signing method.
    8. </Message>
    9. <StringToSignBytes>
    10. 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
    11. </StringToSignBytes>
    12. <RequestId>
    13. 1E446260FF9B10C2
    14. </RequestId>
    15. <HostId>
    16. oss-cn-hangzhou.aliyuncs.com
    17. </HostId>
    18. <SignatureProvided>
    19. y5H7yzPsA/tP4+0tH1HHvPEwUv8=
    20. </SignatureProvided>
    21. <StringToSign>
    22. GET
    23. Wed, 11 May 2011 07:59:25 GMT
    24. /oss-example?acl
    25. </StringToSign>
    26. <OSSAccessKeyId>
    27. AKIAIVAKMSMOY7VOMRWQ
    28. </OSSAccessKeyId>
    29. </Error>

注意:

  • OSS SDKが署名を実装しました。 OSS SDKの使用中に署名の問題について心配する必要はありません。 特定の言語の署名実装の詳細については、OSS SDKのコードを参照してください。 OSS SDKの署名を実装するためのファイルは、次の表のとおりです。
SDK 署名の実装
Java SDK OSSRequestSigner.java
Python SDK auth.py
.Net SDK OssRequestSigner.cs
PHP SDK OssClient.php
C SDK oss_auth.c
JavaScript SDK client.js
Go SDK auth.go
Ruby SDK util.rb
iOS SDK OSSModel.m
Android SDK OSSUtils.java

よくある質問

コンテンツ MD5 の計算方法

  1. Content-MD5 calculation
  2. The message content "123456789" is used as an example. The Content-MD5 value of the string
  3. is calculated as follows:
  4. The algorithm defined in related standards can be simplified to the following:
  5. 1. Calculate the MD5-encrypted 128-bit binary array.
  6. 2. Encode the binary array (instead of the 32-bit string code) with Base64.
  7. Python is used as an example.
  8. The correct calculation code is:
  9. >>> import base64,hashlib
  10. >>> hash = hashlib.md5()
  11. >>> hash.update("0123456789")
  12. >>> base64.b64encode(hash.digest())
  13. 'eB5eJF1ptWaXm4bijSPyxw=='
  14. Note:
  15. The correct code is: hash.digest(), used to calculate a 128-bit binary array
  16. >>> hash.digest()
  17. 'x\x1e^$]i\xb5f\x97\x9b\x86\xe2\x8d#\xf2\xc7'
  18. A common error is encoding the calculated 32-bit string code with Base64.
  19. An incorrect example: hash.hexdigest(), and a visible 32-bit string will be calculated.
  20. >>> hash.hexdigest()
  21. '781e5e245d69b566979b86e28d23f2c7'
  22. Result of encoding the incorrect MD5 value with Base64:
  23. >>> base64.b64encode(hash.hexdigest())
  24. 'NzgxZTVlMjQ1ZDY5YjU2Njk3OWI4NmUyOGQyM2YyYzc='