Object Storage Service (OSS) では、最も一般的な認証方法は、HTTP リクエストの Authorization ヘッダーに署名を含める方法です。POST 署名および URL 署名を除き、すべての OSS 操作は Authorization ヘッダーを使用して認証する必要があります。このトピックでは、V1 署名アルゴリズムを使用してヘッダーに署名を含める方法を説明します。
OSS は、よりセキュリティの高い V4 署名アルゴリズムをサポートしています。V4 署名の使用を推奨します。詳細については、「V4 署名」をご参照ください。
SDK の署名実装
OSS SDK は V1 署名を自動的に処理します。SDK を使用する場合、署名を手動で計算する必要はありません。特定の言語における実装を理解するには、SDK のソースコードをご確認ください。次の表に、各 SDK の署名実装ファイルを示します。
|
SDK |
署名実装 |
|
Java |
|
|
PHP |
|
|
Node.js |
|
|
Browser.js |
|
|
Python |
|
|
.NET |
|
|
Android |
|
|
Go |
|
|
iOS |
|
|
C++ |
|
|
C |
|
|
Ruby |
Authorization フィールドの計算方法
計算方法
Authorization = "OSS " + AccessKeyId + ":" + Signature
Signature = base64(hmac-sha1(AccessKeySecret,
VERB + "\n"
+ Content-MD5 + "\n"
+ Content-Type + "\n"
+ Date + "\n"
+ CanonicalizedOSSHeaders
+ CanonicalizedResource))
パラメータ
|
パラメータ |
タイプ |
必須 |
例 |
説明 |
|
AccessKeyId |
String |
はい |
LTAI******************** |
AccessKey ID と AccessKey Secret で構成される AccessKey ペアです。
|
|
AccessKeySecret |
String |
はい |
yourAccessKeySecret |
|
|
x-oss-security-token |
String |
いいえ |
CAIS******************************** |
Security Token Service (STS) のトークンです。このパラメータは、STS を使用してヘッダーの署名を構築する場合にのみ必要です。セキュリティトークンの取得方法の詳細については、「AssumeRole」をご参照ください。 |
|
VERB |
列挙型 |
はい |
PUT |
PUT、GET、POST、HEAD、DELETE、OPTIONS などの HTTP リクエストメソッドです。 |
|
\n |
String |
いいえ |
\n |
改行文字です。 |
|
Content-MD5 |
String |
いいえ |
eB5e******************** |
リクエストボディの MD5 ハッシュです。この値を計算するには、メッセージボディ (ヘッダーを除く) の 128 ビット MD5 ハッシュを計算し、その結果を Base64 エンコードします。詳細については、「RFC2616 Content-MD5」をご参照ください。 このリクエストヘッダーは、メッセージの整合性チェックに使用できます。受信したコンテンツが送信されたコンテンツと同じ場合、メッセージは有効です。このパラメータは空でもかまいません。 Content-MD5 値の計算方法の詳細については、「Content-MD5の計算方法」をご参照ください。 |
|
Content-Type |
String |
いいえ |
application/octet-stream |
リクエストコンテンツのタイプです。このパラメータは空でもかまいません。 説明
署名を生成するときに Content-Type を設定しない場合、その署名を使用してファイルをアップロードする際にこのパラメータを設定する必要はありません。 |
|
Date |
String |
はい |
Sun, 22 Nov 2015 08:16:38 GMT |
操作の時刻です。値は GMT 形式である必要があり、空にはできません。この値は、リクエストヘッダーの Date または x-oss-date フィールドから取得されます。両方のフィールドが存在する場合、x-oss-date が優先されます。 重要
リクエストの Date ヘッダーで指定された時刻が OSS サーバー時刻と 15 分以上異なる場合、OSS はリクエストを拒否し、HTTP 403 エラーを返します。 |
|
CanonicalizedOSSHeaders |
String |
いいえ |
x-oss-meta-a:a\nx-oss-meta-b:b\nx-oss-meta-c:c\n |
この文字列の構築方法の詳細については、「CanonicalizedOSSHeadersの構築方法」をご参照ください。 |
|
CanonicalizedResource |
String |
はい |
examplebucket |
アクセス対象の OSS リソースです。この文字列は空にできません。 この文字列の構築方法の詳細については、「CanonicalizedResourceの構築方法」をご参照ください。 |
署名の例
-
例1:すべてのパラメータを含む
リクエスト
署名対象の文字列の式
署名対象の文字列
PUT /nelson HTTP/1.0 Content-MD5: eB5e******************** 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\neB5e********************\ntext/html\nWed, 28 Dec 2022 10:27:41 GMT\nx-oss-meta-magic:abracadabra\nx-oss-meta-author:alice\n/examplebucket/nelson
AccessKey ID が LTAI**************** で、AccessKey Secret が yourAccessKeySecret の場合、次の Python コードを使用して署名を計算できます。
import hmac import hashlib import base64 h = hmac.new("yourAccessKeySecret".encode('utf-8'), "PUT\neB5e********************\ntext/html\nWed, 28 Dec 2022 10:27:41 GMT\nx-oss-meta-magic:abracadabra\nx-oss-meta-author:alice\n/examplebucket/nelson".encode('utf-8'), hashlib.sha1) signature = base64.encodebytes(h.digest()) print(signature)計算された署名は
J9Nl************************です。最終的なリクエストは次のように構成されます。PUT /nelson HTTP/1.0 Authorization:OSS LTAI****************:J9Nl************************ Content-Md5: eB5e******************** 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 -
例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\nx-oss-meta-magic:abracadabra\nx-oss-meta-author:alice\n/examplebucket/nelson
この例では、AccessKey ID は LTAI**************** で、AccessKey Secret は yourAccessKeySecret です。次の Python コードは、署名を計算する方法を示しています。
import hmac import hashlib import base64 h = hmac.new("yourAccessKeySecret".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/examplebucket/nelson".encode('utf-8'), hashlib.sha1) signature = base64.encodebytes(h.digest()) print(signature)計算された署名は
Mhb1************************です。最終的なリクエストは次のように構成されます。PUT /nelson HTTP/1.0 Authorization:OSS LTAI****************:Mhb1************************ 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
補足情報
-
指定された AccessKey ID が存在しないか非アクティブの場合、OSS はエラーコード
InvalidAccessKeyIdを含む 403 Forbidden エラーを返します。AccessKey ID がアクティブであるにもかかわらず、OSS がリクエストで署名エラーを検出した場合、OSS は 403 Forbidden エラーを返します。レスポンスには正しい署名対象の文字列が含まれており、署名プロセスの検証に使用できます。次のコードは、サンプルレスポンスを示しています。
<?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> y5H7************************ </SignatureProvided> <StringToSign> GET Wed, 11 May 2011 07:59:25 GMT /examplebucket?acl </StringToSign> <OSSAccessKeyId> AKIA**************** </OSSAccessKeyId> </Error> -
リクエストヘッダーの Authorization 値の形式が正しくない場合、OSS はエラーコード
InvalidArgumentを含む 400 Bad Request エラーを返します。 -
OSS に送信されるすべてのリクエストは、HTTP 1.1 で指定された GMT の日付形式を使用する必要があります。形式は次のとおりです。
例:Wed, 28 Dec 2022 10:27:41 GMT説明上記の日付形式では、
dayは 2 桁の数字です。したがって、Jun 2、2 Jun 1982、2-Jun-1982はすべて無効な日付形式です。-
署名付きリクエストに Date ヘッダーがない場合、または形式が無効な場合、OSS はエラーコード
AccessDeniedを含む 403 Forbidden エラーを返します。 -
リクエストの時刻は、OSS サーバーの現在時刻から 15 分以内でなければなりません。それ以外の場合、OSS はエラーコード
RequestTimeTooSkewedを含む 403 Forbidden エラーを返します。
-
CanonicalizedOSSHeaders の構築方法
x-oss- で始まるすべての HTTP ヘッダーは、正規化 OSS ヘッダーと呼ばれます。CanonicalizedOSSHeaders 文字列を構築するには、次の手順に従います。
-
x-oss-で始まるすべての HTTP リクエストヘッダーの名前を小文字に変換します。たとえば、X-OSS-Meta-Name: TaoBaoをx-oss-meta-name: TaoBaoに変換します。 -
Security Token Service (STS) の一時的なアクセス認証情報を使用してリクエストを送信する場合は、署名対象の文字列に
x-oss-security-token:security-tokenの形式でセキュリティトークンを追加します。説明STS の構成方法の詳細については、「STS が提供する一時的な認証情報を使用した OSS へのアクセス」をご参照ください。AssumeRole API を呼び出すか、各種プログラミング言語用の STS SDK を使用して一時的なアクセス認証情報を取得できます。一時的なアクセス認証情報には、セキュリティトークンと一時的な AccessKey ペアが含まれます。AccessKey ペアは、AccessKey ID と AccessKey Secret で構成されます。
-
取得したすべての HTTP リクエストヘッダーをヘッダー名で辞書順にソートします。
-
ヘッダー名と値を区切るコロンの前後の空白を削除します。たとえば、
x-oss-meta-name: TaoBaoをx-oss-meta-name:TaoBaoに変換します。 -
処理されたヘッダーを連結します。各ヘッダーを改行文字 (
\n) で区切って、CanonicalizedOSSHeaders 文字列を作成します。
CanonicalizedResource の構築方法
リクエストでアクセスするターゲット OSS リソースは、正規化リソースと呼ばれます。CanonicalizedResource 文字列を構築するには、次のルールに従います。
-
リソースにバケットとオブジェクトが含まれる場合は、CanonicalizedResource を /BucketName/ObjectName に設定します。
-
リソースにバケットのみが含まれる場合は、CanonicalizedResource を /BucketName/ に設定します。
-
リソースにバケットもオブジェクトも含まれない場合は、CanonicalizedResource をフォワードスラッシュ (/) に設定します。
-
リクエストにサブリソースが含まれる場合は、すべてのサブリソースを辞書順にソートし、アンパサンド (
&) で連結してサブリソース文字列を作成します。疑問符 (?) とサブリソース文字列を CanonicalizedResource 文字列の末尾に追加します。結果として得られる CanonicalizedResource 文字列は、/BucketName/ObjectName?acl&uploadId=UploadIdの形式になります。OSS は次の 4 種類のサブリソースをサポートしています。
-
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 などのリソース識別子です。詳細については、「バケット操作」と「オブジェクト操作」をご参照ください。
重要リソース識別子では大文字と小文字が区別されます。
-
response-content-language、response-expires、response-cache-control、response-content-disposition、response-content-encoding などのレスポンスヘッダーフィールドです。詳細については、「GetObject」をご参照ください。
-
x-oss-processなどの画像処理方法です。詳細については、「画像処理」をご参照ください。 -
x-oss-ac-source-ip、x-oss-ac-subnet-mask、x-oss-ac-vpc-id、x-oss-ac-forward-allow など、
x-oss-ac-*で始まるアクセス制御フィールドです。詳細については、「署名バージョン1」をご参照ください。説明x-oss-ac-source-ip パラメータを含む CanonicalizedResource 文字列を使用して署名を生成した後、IP アドレスを保護するため、リクエストのクエリパラメータから x-oss-ac-source-ip を削除してください。
-
署名計算ルール
-
署名対象の文字列は
UTF-8形式である必要があります。中国語の文字を含む文字列は、UTF-8でエンコードした上で、AccessKeySecretと組み合わせて署名を計算する必要があります。 -
署名は、RFC 2104 で定義されている HMAC-SHA1 メソッドを使用して計算されます。計算のキーは、AccessKey Secret です。
-
Content-TypeとContent-MD5は、リクエストで必須ではありません。これらのヘッダーが署名検証を必要とするリクエストに含まれていない場合でも、署名対象の文字列にはそれぞれの改行文字 (\n) を含める必要があります。 -
x-oss-で始まる非標準 HTTP ヘッダーのみを署名対象の文字列に含める必要があります。たとえば、署名の例の x-oss-meta-magic ヘッダーは含める必要があります。その他の非標準 HTTP ヘッダーは OSS によって無視されます。説明x-oss-で始まるヘッダーは、署名検証の前に次のルールに従って処理する必要があります。-
ヘッダー名は小文字である必要があります。
-
ヘッダーは名前で辞書順にソートする必要があります。
-
ヘッダー名と値を区切るコロンの前後にスペースがあってはなりません。
-
各ヘッダーは改行文字 (\n) で区切る必要があります。このようなヘッダーが指定されていない場合、CanonicalizedOSSHeaders 文字列は空です。
-
Content-MD5 の計算方法
このセクションでは、メッセージコンテンツ「0123456789」を例として、Content-MD5 値の正しい計算方法と誤った計算方法を示します。
-
正しい計算方法
-
まず、128 ビットのバイナリ配列である MD5 ハッシュを計算します。
-
32 文字の 16 進数文字列ではなく、バイナリ配列を Base64 エンコードします。
次の例は Python を使用しています。
>>> import base64,hashlib >>> hash = hashlib.md5() >>> hash.update(b"0123456789") # Python 2 の場合は hash.update("0123456789") を使用します >>> base64.b64encode(hash.digest()) 'eB5e********************'hash.digest() メソッドは 128 ビットのバイナリ配列を返します。
>>> hash.digest() 'x\x1e^$]i\xb5f\x97\x9b\x86\xe2\x8d#\xf2\xc7' -
-
誤った計算方法の例
説明よくある間違いは、32 文字の 16 進数文字列を直接 Base64 エンコードすることです。
# hash.hexdigest() メソッドは、表示可能な 32 文字の 16 進数文字列を計算します。 >>> hash.hexdigest() '781e****************************' # 誤った MD5 ハッシュを Base64 エンコードした結果です。 >>> base64.b64encode(hash.hexdigest()) 'Nzgx****************************************'