Web クライアントから Object Storage Service (OSS) にオブジェクトをアップロードし、アップロードコールバックを構成するには、PostObject オペレーションを呼び出すことができます。この場合、アップロードプロセス中のオブジェクトのセキュリティを確保するために、アプリケーションサーバーで生成された署名を使用できます。また、ビジネス要件に合わせてアップロードポリシーを構成することもできます。
ワークフロー
次の図は、アプリケーションサーバーで署名を生成し、Web クライアントから OSS にオブジェクトをアップロードする方法を示しています。
リクエストに署名を追加し、OSS にオブジェクトをアップロードして、アップロードコールバックを構成するには、次の手順を実行します。
このプロセスでは、一時的なアクセス認証情報が使用されます。これにより、アプリケーションサーバーの AccessKey ペアの漏洩を防ぎ、アップロードプロセス中のオブジェクトのセキュリティを確保します。
OSS を構成する: OSS コンソールで、アップロードされたオブジェクトを格納するバケットを作成します。次に、アプリケーションサーバーからのクロスオリジンリクエストを許可するように、バケットのオリジン間リソース共有 (CORS) ルールを構成します。
アプリケーションサーバーを構成する: アプリケーションサーバーにプリセットされている一時的なアクセス認証情報とアップロードポリシーを使用して署名を生成し、特定の期間内にオブジェクトをアップロードする権限をユーザーに付与します。プリセットのアップロードポリシーには、バケット名、ディレクトリパス、有効期限などの情報が含まれています。アプリケーションサーバーは、OSS から送信されたメッセージに含まれる
authorizationヘッダーに基づいて署名を確認します。検証に成功すると、アプリケーションサーバーは JSON 形式の次のメッセージを OSS に返します。Web クライアントを構成する: HTML フォームを作成し、そのフォームを使用して署名を送信し、オブジェクトを OSS にアップロードします。OSS はクライアントのアップロードコールバック構成を解析し、POST コールバックリクエストをアプリケーションサーバーに送信します。
デモプロジェクト
Java のデモプロジェクトについては、「server-signed-direct-upload-callback-java.zip」をご参照ください。
Python のデモプロジェクトについては、「server-signed-direct-upload-callback-python.zip」をご参照ください。
Go のデモプロジェクトについては、「server-signed-direct-upload- callback-go.zip」をご参照ください。
Node.js のデモプロジェクトについては、「server-signed-direct-upload-callback-nodejs.zip」をご参照ください。
PHP のデモプロジェクトについては、「server-signed-direct-upload-callback-php.zip」をご参照ください。
手順
ステップ 1: OSS を構成する
1. バケットを作成する
ブラウザから Web アプリケーションによってアップロードされたデータを格納する OSS バケットを作成します。
OSS コンソール にログインします。
左側のナビゲーションウィンドウで、[バケットリスト] をクリックします。バケット ページで、バケットの作成 をクリックします。
バケットの作成 パネルで、パラメータを構成します。次の表にパラメータを示します。
パラメータ
例
バケット名
web-direct-upload- callback
リージョン
中国 (杭州)
OK をクリックします。
2. CORS ルールを構成する
作成したバケットの CORS ルールを構成します。
バケット ページで、バケットの名前をクリックします。
表示されるページの左側のナビゲーションツリーで、[コンテンツセキュリティ] > [クロスオリジンリソース共有の設定] を選択します。 クロスオリジンリソース共有の設定 ページで、ルールの作成 をクリックします。
ルールの作成 パネルで、パラメータを構成します。次の表にパラメータを示します。
パラメータ
例
ソース
*
許可されたメソッド
POST、PUT、および GET
許可されたヘッダー
*
OK をクリックします。
ステップ 2: アプリケーションサーバーを構成する
実際のデプロイでは、独自のアプリケーションサーバーがある場合、「準備: アプリケーションサーバーとして ECS インスタンスを作成する」セクションの操作を実行する必要はなく、1. ユーザー権限を構成する にリダイレクトされます。
準備: アプリケーションサーバーとして ECS インスタンスを作成する
操作 1: ECS インスタンスを作成する
Elastic Compute Service (ECS) コンソールのインスタンス購入ページの カスタム起動 タブに移動します。次に、次の手順に基づいて、ECS インスタンスに必要な基本リソースを作成または選択します。
リージョンと課金方法を選択する
ビジネス要件に基づいて課金方法を選択します。この例では、従量課金の課金方法が選択されています。この課金方法では、他の課金方法と比較して、より柔軟な操作を実行できます。
ビジネスのネットワーク遅延要件に基づいてリージョンを選択します。ネットワーク遅延を低く抑え、アクセス速度を上げるには、ユーザーに近いリージョンを選択することをお勧めします。この例では、中国 (杭州) リージョンが選択されています。

VPC と vSwitch を作成する
仮想プライベートクラウド (VPC) を作成するときは、ECS インスタンスを作成したリージョンを選択し、ビジネス要件に基づいて CIDR ブロックを計画します。この例では、VPC と vSwitch が 中国 (杭州) リージョンに作成されます。VPC を作成したら、ECS コンソールのインスタンス購入ページのカスタム起動タブに戻り、VPC と vSwitch のドロップダウンリストを更新してから、作成した VPC と vSwitch を選択します。
説明VPC を作成するときに vSwitch を作成することもできます。



インスタンスタイプとイメージを選択する
インスタンスタイプとイメージを選択します。インスタンスの作成時に、イメージに含まれるオペレーティングシステムバージョンがインスタンスにインストールされます。この例では、費用対効果の高い
ecs.e-c1m1.largeインスタンスタイプとAlibaba Cloud Linux 3.2104 LTS 64 ビットパブリックイメージが選択されています。
ストレージを選択する
ビジネス要件に基づいて、ECS インスタンスのシステムディスクとデータディスクを構成します。このトピックでは、ECS インスタンスにシンプルな Web サービスをセットアップする方法について説明します。これには、インスタンスのオペレーティングシステムを格納するためのシステムディスクのみが必要です。

パブリック IP アドレスを割り当てる
ECS インスタンスにインターネット接続を提供するには、[パブリック IPv4 アドレスの割り当て] を選択して、インスタンスにパブリック IP アドレスを割り当てます。または、インスタンスの作成後に、ECS インスタンスに Elastic IP アドレス (EIP) を関連付けることもできます。詳細については、「EIP を ECS インスタンスに関連付ける」をご参照ください。
説明ECS インスタンスにパブリック IP アドレスを割り当てたり、EIP を関連付けたりしないと、SSH または RDP (Remote Desktop Protocol) 経由でインスタンスにアクセスしたり、インターネット経由でインスタンスにデプロイされている Web サービスをテストしたりすることはできません。
[パブリック IPv4 アドレスの割り当て] を選択した後、[帯域幅課金方法] パラメータを構成して、ネットワーク使用量の課金方法を指定します。この例では、[帯域幅課金方法] パラメータは トラフィック課金 に設定されています。トラフィック課金方式では、インターネット経由で転送されたデータ量に基づいて課金されます。詳細については、「パブリック帯域幅」をご参照ください。

セキュリティグループを作成する
ECS インスタンスのセキュリティグループを作成します。セキュリティグループは、ECS インスタンスのインバウンドトラフィックとアウトバウンドトラフィックを制御できる仮想ファイアウォールとして機能します。セキュリティグループを作成するときは、次のポートを開いて ECS インスタンスへのアクセスを許可します。
IPv4 ポート/プロトコルの開放: SSH (TCP:22)、RDP (TCP:3389)、HTTP (TCP:80)、および HTTPS (TCP:443) を選択します。
説明Ipv4 ポート/プロトコルの開放 セクションで、ECS インスタンスで実行されるアプリケーションで開いている必要があるポートを選択します。
デフォルトでは、新しいセキュリティグループには、ソースアドレスとして 0.0.0.0/0 を参照するルールが作成されます。0.0.0.0/0 はすべての IP アドレスを表します。このルールでは、指定されたポートで、すべての IP アドレスから ECS インスタンスへのアクセスが許可されます。ECS インスタンスを作成した後、特定の IP アドレスからのみインスタンスへのアクセスを許可するようにルールを変更することをお勧めします。詳細については、「セキュリティグループルールを変更する」をご参照ください。

キーペアを作成する
キーペアを ECS インスタンスにバインドし、インスタンスにログインするときにキーペアをセキュリティ認証情報として使用して ID を認証できます。キーペアを作成した後、ECS インスタンスに接続するときに後で使用するために、キーペアの秘密鍵をダウンロードします。詳細については、「ECS インスタンスに接続する」をご参照ください。キーペアを作成した後、インスタンス購入ページのカスタム起動タブに戻り、[キーペア] ドロップダウンリストを更新してから、作成したキーペアを選択します。
rootは、オペレーティングシステムで最も権限の高いアカウントです。ログインユーザー名としてrootを選択すると、セキュリティリスクが発生する可能性があります。ログインユーザー名としてecs-userを選択することをお勧めします。説明キーペアを作成すると、キーペアの秘密鍵が自動的にダウンロードされます。ブラウザのダウンロード履歴を表示し、
.pem形式の秘密鍵ファイルを保存します。
ECS インスタンスを作成して表示する
必要な基本リソースを作成または選択した後、ECS サービス利用規約 と プロダクトサービス利用規約 を読んで選択します。次に、[注文を作成] をクリックします。[成功] メッセージで、[コンソール] をクリックして、[インスタンス] ページで作成された ECS インスタンスを表示します。後で使用するために、次の情報を記録します。
インスタンス ID: インスタンス ID で ECS インスタンスを検索できます。
リージョン: リージョンで ECS インスタンスを検索できます。
パブリック IP アドレス: ECS インスタンスのパブリック IP アドレスを使用して、Web サービスがインスタンスにデプロイされているかどうかを確認できます。


操作 2: ECS インスタンスに接続する
ECS コンソール の インスタンス ページで、リージョンと ID に基づいて作成した ECS インスタンスを見つけます。次に、[操作] 列の [接続] をクリックします。

[リモート接続] ダイアログボックスで、[ワークベンチ] セクションの [今すぐサインイン] をクリックします。

[Instance Login] ダイアログボックスで、[Authentication] パラメータを SSH Key Authentication に設定し、[Username] パラメータを
ecs-userに設定し、キーペアの作成時にダウンロードした秘密鍵ファイルを入力またはアップロードして、[OK] をクリックします。説明キーペアを作成すると、キーペアの秘密鍵が自動的にオンプレミスコンピュータにダウンロードされます。
.pem形式の秘密鍵ファイルを見つけるには、ブラウザのダウンロード履歴を表示します。
次の図に示すようなページが表示されたら、ECS インスタンスにログインしています。

1. ユーザー権限を構成する
デプロイメントの完了後に、権限のない操作が原因でローカルファイルのアップロードが失敗するのを防ぐために、次の手順を実行して RAM ユーザーを作成し、必要な権限を RAM ユーザーに付与することをお勧めします。
操作 1: RAM コンソールで RAM ユーザーを作成する
RAM ユーザーを作成し、RAM ユーザーの AccessKey ペアを取得します。AccessKey ペアは、アプリケーションサーバーにアクセスして管理するために必要な長期アクセス認証情報です。
Alibaba Cloud アカウントまたはアカウント管理者として、RAM コンソール にログインします。
左側のナビゲーションウィンドウで、[Identities] > [Users] を選択します。
[ユーザー] ページで、[ユーザーの作成] をクリックします。
[ログイン名] パラメータと [表示名] パラメータを構成します。
[アクセスモード] セクションで、[永続 Accesskey を使用してアクセスする] を選択し、[OK] をクリックします。
RAM ユーザーの AccessKey シークレットは、RAM ユーザーの作成時にのみ取得できます。認証情報の漏洩を防ぐために、AccessKey シークレットを安全に保管する必要があります。
表示されるページの [操作] 列の [コピー] をクリックして、AccessKey ペアをコピーして安全に保管されたファイルに貼り付けます。
操作 2: RAM コンソールで RAM ユーザーに AssumeRole オペレーションを呼び出す権限を付与する
RAM ユーザーに AssumeRole オペレーションを呼び出す権限を付与します。これにより、RAM ユーザーは RAM ロールを引き受けることによって一時的なアクセス認証情報を取得できます。
左側のナビゲーションウィンドウで、[Identities] > [Users] を選択します。
[ユーザー] ページで、権限を付与する RAM ユーザーを見つけ、[操作] 列の [権限の追加] をクリックします。
[権限の付与] パネルの [ポリシー] セクションで、AliyunSTSAssumeRoleAccess システムポリシーを選択します。
説明AliyunSTSAssumeRoleAccess ポリシーでは、RAM ユーザーが AssumeRole オペレーションを呼び出すことができます。ポリシーの権限は、RAM ユーザーが STS から一時的なアクセス認証情報を取得し、OSS にリクエストを開始するために必要な権限とは無関係です。
[権限の付与] をクリックします。
操作 3: RAM コンソールで RAM ロールを作成する
Alibaba Cloud アカウントの RAM ロールを作成し、RAM ロールの Alibaba Cloud Resource Name (ARN) を取得します。RAM ロールは後で RAM ユーザーによって引き受けられます。
左側のナビゲーションウィンドウで、[ID] > [ロール] を選択します。
[ロール] ページで、[ロールの作成] をクリックします。[ロールタイプの選択] ステップで、[信頼できるエンティティの選択] パラメータを Alibaba Cloud アカウント に設定し、[次へ] をクリックします。
[ロールの構成] ステップで、[RAM ロール名] フィールドに名前を入力し、[信頼できる Alibaba Cloud アカウントの選択] パラメータを 現在の Alibaba Cloud アカウント に設定します。
[OK] をクリックします。ロールを作成した後、[閉じる] をクリックします。
[ロール] ページで、検索ボックスにロール名を入力します。例:
oss-web-upload。ロールの名前をクリックします。[基本情報] セクションで、ARN フィールドの横にある [コピー] をクリックして、RAM ロールの ARN を記録します。
操作 4: RAM コンソールでカスタムポリシーを作成するRAM コンソールで
最小権限の原則に基づいてカスタムポリシーを作成し、特定のバケットにのみデータをアップロードする権限を RAM ロールに付与します。
左側のナビゲーションウィンドウで、[権限] > [ポリシー] を選択します。
[ポリシー] ページで、[ポリシーの作成] をクリックします。
[ポリシーの作成] ページで、[JSON] をクリックします。次のサンプルスクリプトをコピーして、コードエディタに貼り付けます。
<BucketName>を、作成したバケットの名前 (web-direct-upload) に置き換えます。{ "Version": "1", "Statement": [ { "Effect": "Allow", "Action": "oss:PutObject", "Resource": "acs:oss:*:*:<BucketName>/*" } ] }ポリシーを構成した後、[ポリシー情報を編集するために次へ] をクリックします。
[基本情報] セクションで、ポリシー名を指定し、[OK] をクリックします。
操作 5: RAM コンソールでカスタムポリシーを RAM ロールにアタッチする
カスタムポリシーを RAM ロールにアタッチします。これにより、RAM ロールが引き受けられたときに、RAM ロールに必要な権限が付与されます。
左側のナビゲーションウィンドウで、[権限] > [ロール] を選択します。
[ロール] ページで、RAM ロールを見つけ、[操作] 列の [権限の付与] をクリックします。
[権限の付与] パネルの [ポリシー] セクションで、ドロップダウンリストから [カスタムポリシー] を選択し、カスタムポリシーを選択します。
[権限の付与] をクリックします。
2. アプリケーションサーバーで一時的なアクセス認証情報を取得し、署名を計算する
コードで accessKeyId、accessKeySecret、roleArn などの機密情報を明示的に指定することによるリスクを防ぐために、機密情報を環境変数に構成することをお勧めします。
環境変数を一時的な環境変数として追加し、現在のセッションでのみ使用できます。
Linux
次のコマンドを実行します。
export OSS_ACCESS_KEY_ID="your-access-key-id" export OSS_ACCESS_KEY_SECRET="your-access-key-secret" export OSS_STS_ROLE_ARN="your-role-arn"次のコマンドを実行して、環境変数が有効になっているかどうかを確認します。
echo $OSS_ACCESS_KEY_ID echo $OSS_ACCESS_KEY_SECRET echo $OSS_STS_ROLE_ARN
macOS
次のコマンドを実行します。
export OSS_ACCESS_KEY_ID="your-access-key-id" export OSS_ACCESS_KEY_SECRET="your-access-key-secret" export OSS_STS_ROLE_ARN="your-role-arn"次のコマンドを実行して、環境変数が有効になっているかどうかを確認します。
echo $OSS_ACCESS_KEY_ID echo $OSS_ACCESS_KEY_SECRET echo $OSS_STS_ROLE_ARN
Windows
cmd で次のコマンドを実行します。
set OSS_ACCESS_KEY_ID "your-access-key-id" set OSS_ACCESS_KEY_SECRET "your-access-key-secret" set OSS_STS_ROLE_ARN "your-role-arn"新しいウィンドウを開きます。
新しいウィンドウで次のコマンドを実行して、環境変数が有効になっているかどうかを確認します。
echo $OSS_ACCESS_KEY_ID echo $OSS_ACCESS_KEY_SECRET echo $OSS_STS_ROLE_ARN
次のサンプルコードは、サーバー上の PostObject リクエストで V4 署名を計算する方法の例を示しています。詳細については、「署名バージョン 4 (推奨)」をご参照ください。PostObject リクエストのポリシーフォームフィールドの構成については、「ポリシー」をご参照ください。
Java
Maven プロジェクトに次の依存関係を追加します。
<!-- https://mvnrepository.com/artifact/com.aliyun/credentials-java -->
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>credentials-java</artifactId>
<version>0.3.4</version>
</dependency>
<dependency>
<groupId>com.aliyun.kms</groupId>
<artifactId>kms-transfer-client</artifactId>
<version>0.1.0</version>
</dependency>
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>3.17.4</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>sts20150401</artifactId>
<version>1.1.6</version>
</dependency>次のサンプルコードは、一時的なアクセス認証情報を取得し、オブジェクトのアップロードに使用できる署名を計算し、アップロードコールバックを構成する方法の例を示しています。
package com.aliyun.oss.web;
import com.aliyun.sts20150401.models.AssumeRoleResponse;
import com.aliyun.sts20150401.models.AssumeRoleResponseBody;
import com.aliyun.tea.TeaException;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.codec.binary.Base64;
import org.codehaus.jettison.json.JSONObject;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.*;
@Controller
public class WebController {
// 基本情報を指定します。値を実際のバケット名、リージョン ID、およびホストエンドポイントに置き換えます。
String bucket = "examplebucket";
String region = "cn-hangzhou";
String host = "http://examplebucket.oss-cn-hangzhou.aliyuncs.com";
// アップロードコールバックリクエストの送信先のアプリケーションサーバーの URL を指定します。URL はパブリックドメイン名である必要があります。この URL は、アプリケーションサーバーと OSS 間の通信に使用されます。オブジェクトをアップロードした後、OSS はこの URL を使用してアップロード情報をアプリケーションサーバーに送信します。
String callbackUrl = "http://oss-demo.aliyuncs.com:23450/callback"; // コールバックリクエストを受信するコールバックサーバーのアドレスを指定します。例: http://oss-demo.aliyuncs.com:23450/callback。
// OSS にアップロードするオブジェクトの名前に含まれるプレフィックスを指定します。
String upload_dir = "dir";
// 一時的なアクセス認証情報の有効期間を指定します。単位: 秒。
Long expire_time = 3600L;
/**
* 有効期限は、指定された有効期間に基づいて計算されます。単位: 秒。
* @param seconds: 有効期間 (秒単位)。
* @return: ISO 8601 標準の時間文字列。例: 2014-12-01T12:00:00.000Z。
*/
public static String generateExpiration(long seconds) {
// 現在のタイムスタンプを取得します。単位: 秒。
long now = Instant.now().getEpochSecond();
// 有効期限のタイムスタンプを計算します。
long expirationTime = now + seconds;
// タイムスタンプをインスタントオブジェクトに変換し、ISO 8601 標準でフォーマットします。
Instant instant = Instant.ofEpochSecond(expirationTime);
// タイムゾーンを定義します。
ZoneId zone = ZoneId.systemDefault(); // システムのデフォルトのタイムゾーンが使用されるように指定します。
// インスタンスオブジェクトを ZonedDateTime オブジェクトに変換します。
ZonedDateTime zonedDateTime = instant.atZone(zone);
// 時間形式を指定します。例: 2023-12-03T13:00:00.000Z。
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
// 時間をフォーマットします。
String formattedDate = zonedDateTime.format(formatter);
// 結果を出力します。
return formattedDate;
}
// STSClient インスタンスを初期化します。
public static com.aliyun.sts20150401.Client createStsClient() throws Exception {
// プロジェクトコードが漏洩した場合、AccessKey ペアが漏洩し、アカウント内のすべてのリソースのセキュリティが危険にさらされる可能性があります。次のサンプルコードは参考用としてのみ提供されています。
// セキュリティを強化するために、STS から取得したアクセス認証情報を使用することをお勧めします。
com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config()
// 必須。OSS_ACCESS_KEY_ID 環境変数が構成されていることを確認します。
.setAccessKeyId(System.getenv("OSS_ACCESS_KEY_ID"))
// 必須。OSS_ACCESS_KEY_SECRET 環境変数が構成されていることを確認します。
.setAccessKeySecret(System.getenv("OSS_ACCESS_KEY_SECRET"));
// バケットが配置されているリージョンのエンドポイントを指定します。詳細については、https://api.aliyun.com/product/Sts をご覧ください。
config.endpoint = "sts.cn-hangzhou.aliyuncs.com";
return new com.aliyun.sts20150401.Client(config);
}
// STS からセキュリティトークンを取得します。
public static AssumeRoleResponseBody.AssumeRoleResponseBodyCredentials getCredential() throws Exception {
com.aliyun.sts20150401.Client client = WebController.createStsClient();
com.aliyun.sts20150401.models.AssumeRoleRequest assumeRoleRequest = new com.aliyun.sts20150401.models.AssumeRoleRequest()
// 必須。OSS_STS_ROLE_ARN 環境変数が構成されていることを確認します。
.setRoleArn(System.getenv("OSS_STS_ROLE_ARN"))
.setRoleSessionName("yourRoleSessionName");// カスタムセッション名を指定します。
com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
try {
// 必要に応じて、API オペレーションのレスポンスを表示する独自のコードを記述します。
AssumeRoleResponse response = client.assumeRoleWithOptions(assumeRoleRequest, runtime);
// 後続の操作に必要な AccessKey ID、AccessKey シークレット、およびセキュリティトークンは、アクセス認証情報に含まれています。
return response.body.credentials;
} catch (TeaException error) {
// 実際のビジネスシナリオでは例外を慎重に処理し、プロジェクトで例外を無視しないでください。この例では、例外は参考用としてのみ提供されています。
// エラーメッセージを表示します。
System.out.println(error.getMessage());
// トラブルシューティング情報を表示します。
System.out.println(error.getData().get("Recommend"));
com.aliyun.teautil.Common.assertAsString(error.message);
} catch (Exception _error) {
TeaException error = new TeaException(_error.getMessage(), _error);
// 実際のビジネスシナリオでは例外を慎重に処理し、プロジェクトで例外を無視しないでください。この例では、例外は参考用としてのみ提供されています。
// エラーメッセージを表示します。
System.out.println(error.getMessage());
// トラブルシューティング情報を表示します。
System.out.println(error.getData().get("Recommend"));
com.aliyun.teautil.Common.assertAsString(error.message);
}
return null;
}
@GetMapping("/get_post_signature_for_oss_upload")
public ResponseEntity<Map<String, String>> getPostSignatureForOssUpload() throws Exception {
AssumeRoleResponseBody.AssumeRoleResponseBodyCredentials sts_data = getCredential();
String accesskeyid = sts_data.accessKeyId;
String accesskeysecret = sts_data.accessKeySecret;
String securitytoken = sts_data.securityToken;
// x-oss-credential ヘッダーの現在の日付を取得します。値は yyyyMMdd 形式です。
LocalDate today = LocalDate.now();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
String date = today.format(formatter);
// x-oss-date ヘッダーを取得します。
ZonedDateTime now = ZonedDateTime.now().withZoneSameInstant(java.time.ZoneOffset.UTC);
DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("yyyyMMdd'T'HHmmss'Z'");
String x_oss_date = now.format(formatter2);
// ステップ 1: ポリシーを作成します。
String x_oss_credential = accesskeyid + "/" + date + "/" + region + "/oss/aliyun_v4_request";
ObjectMapper mapper = new ObjectMapper();
Map<String, Object> policy = new HashMap<>();
policy.put("expiration", generateExpiration(expire_time));
List<Object> conditions = new ArrayList<>();
Map<String, String> bucketCondition = new HashMap<>();
bucketCondition.put("bucket", bucket);
conditions.add(bucketCondition);
Map<String, String> securityTokenCondition = new HashMap<>();
securityTokenCondition.put("x-oss-security-token", securitytoken);
conditions.add(securityTokenCondition);
Map<String, String> signatureVersionCondition = new HashMap<>();
signatureVersionCondition.put("x-oss-signature-version", "OSS4-HMAC-SHA256");
conditions.add(signatureVersionCondition);
Map<String, String> credentialCondition = new HashMap<>();
credentialCondition.put("x-oss-credential", x_oss_credential); // 値を AccessKey ID に置き換えます。
conditions.add(credentialCondition);
Map<String, String> dateCondition = new HashMap<>();
dateCondition.put("x-oss-date", x_oss_date);
conditions.add(dateCondition);
conditions.add(Arrays.asList("content-length-range", 1, 10240000));
conditions.add(Arrays.asList("eq", "$success_action_status", "200"));
conditions.add(Arrays.asList("starts-with", "$key", upload_dir));
policy.put("conditions", conditions);
String jsonPolicy = mapper.writeValueAsString(policy);
// ステップ 2: 署名する文字列を作成します。
String stringToSign = new String(Base64.encodeBase64(jsonPolicy.getBytes()));
// ステップ 3: 署名キーを計算します。
byte[] dateKey = hmacsha256(("aliyun_v4" + accesskeysecret).getBytes(), date);
byte[] dateRegionKey = hmacsha256(dateKey, region);
byte[] dateRegionServiceKey = hmacsha256(dateRegionKey, "oss");
byte[] signingKey = hmacsha256(dateRegionServiceKey, "aliyun_v4_request");
// ステップ 4: 署名を計算します。
byte[] result = hmacsha256(signingKey, stringToSign);
String signature = BinaryUtil.toHex(result);
// ステップ 5: コールバックを構成します。
JSONObject jasonCallback = new JSONObject();
jasonCallback.put("callbackUrl", callbackUrl);
jasonCallback.put("callbackBody","filename=${object}&size=${size}&mimeType=${mimeType}&height=${imageInfo.height}&width=${imageInfo.width}");
jasonCallback.put("callbackBodyType", "application/x-www-form-urlencoded");
String base64CallbackBody = BinaryUtil.toBase64String(jasonCallback.toString().getBytes());
Map<String, String> response = new HashMap<>();
// レスポンスマッピングにデータを追加します。
response.put("version", "OSS4-HMAC-SHA256");
// この構成はエラーが発生しやすいです。ポリシーをアップロードする前に Base64 エンコーディングを実行する必要があります。
response.put("policy", stringToSign);
response.put("x_oss_credential", x_oss_credential);
response.put("x_oss_date", x_oss_date);
response.put("signature", signature);
response.put("security_token", securitytoken);
response.put("dir", upload_dir);
response.put("host", host);
response.put("callback", base64CallbackBody);
// 200 OK ステータスコードを含む ResponseEntity クラスを Web クライアントに返します。その後、クライアントは PostObject オペレーションを実行できます。
return ResponseEntity.ok(response);
}
public static byte[] hmacsha256(byte[] key, String data) {
try {
// HMAC キーの仕様を初期化し、アルゴリズムを HMAC-SHA256 に設定し、指定されたキーを使用します。
SecretKeySpec secretKeySpec = new SecretKeySpec(key, "HmacSHA256");
// Mac インスタンスを取得し、getInstance メソッドを使用してアルゴリズムを HMAC-SHA256 に設定します。
Mac mac = Mac.getInstance("HmacSHA256");
// キーを使用して Mac インスタンスを初期化します。
mac.init(secretKeySpec);
// HMAC 値を計算します。doFinal メソッドを使用して計算するデータを受信し、計算結果を配列で返します。
byte[] hmacBytes = mac.doFinal(data.getBytes());
return hmacBytes;
} catch (Exception e) {
throw new RuntimeException("HMAC-SHA256 の計算に失敗しました", e);
}
}
}Python
次のコマンドを実行して、依存関係をインストールします。
pip install flask
pip install alibabacloud_tea_openapi alibabacloud_sts20150401 alibabacloud_credentials次のサンプルコードは、STS から一時的なアクセス認証情報を取得し、オブジェクトのアップロードに使用できる署名を計算し、アップロードコールバックを構成する方法の例を示しています。
from flask import Flask, render_template, jsonify, request
from alibabacloud_tea_openapi.models import Config
from alibabacloud_sts20150401.client import Client as Sts20150401Client
from alibabacloud_sts20150401 import models as sts_20150401_models
import os
import json
import base64
import hmac
import datetime
import time
import hashlib
import oss2
app = Flask(__name__)
# OSS_ACCESS_KEY_ID、OSS_ACCESS_KEY_SECRET、および OSS_STS_ROLE_ARN 環境変数を構成します。
access_key_id = os.environ.get('OSS_ACCESS_KEY_ID')
access_key_secret = os.environ.get('OSS_ACCESS_KEY_SECRET')
role_arn_for_oss_upload = os.environ.get('OSS_STS_ROLE_ARN')
# セッション名を指定します。
role_session_name = 'yourRoleSessionName'
# 値を実際のバケット名、リージョン ID、およびホストエンドポイントに置き換えます。
bucket = ' examplebucket'
region_id = 'cn-hangzhou'
host = 'http://examplebucket.oss-cn-hangzhou.aliyuncs.com'
# 一時的なアクセス認証情報の有効期間を指定します。単位: 秒。
expire_time = 3600
# OSS のオブジェクトの名前にプレフィックスを指定します。
upload_dir = 'dir'
def hmacsha256(key, data):
"""
HMAC-SHA256 値の計算に使用する関数を指定します。
:param key: ハッシュ値の計算に使用するキー。キーはバイト型です。
:param data: ハッシュ値を計算するデータ。データは文字列型です。
:return: 計算された HMAC-SHA256 値。値はバイト型です。
"""
try:
mac = hmac.new(key, data.encode(), hashlib.sha256)
hmacBytes = mac.digest()
return hmacBytes
except Exception as e:
raise RuntimeError(f"HMAC-SHA256 の計算に失敗しました: {e}")
@app.route("/")
def hello_world():
return render_template('index.html')
@app.route('/get_post_signature_for_oss_upload', methods=['GET'])
def generate_upload_params():
# 構成を初期化し、認証情報を渡します。
config = Config(
region_id=region_id,
access_key_id=access_key_id,
access_key_secret=access_key_secret
)
# STSClient インスタンスを作成し、一時的なアクセス認証情報を取得します。
sts_client = Sts20150401Client(config=config)
assume_role_request = sts_20150401_models.AssumeRoleRequest(
role_arn=role_arn_for_oss_upload,
role_session_name=role_session_name
)
response = sts_client.assume_role(assume_role_request)
token_data = response.body.credentials.to_map()
# STS から返された一時的なアクセス認証情報を使用します。
temp_access_key_id = token_data['AccessKeyId']
temp_access_key_secret = token_data['AccessKeySecret']
security_token = token_data['SecurityToken']
now = int(time.time())
# タイムスタンプを datetime オブジェクトに変換します。
dt_obj = datetime.datetime.utcfromtimestamp(now)
# リクエストの有効期限を現在の時刻から 3 時間後に設定します。
dt_obj_plus_3h = dt_obj + datetime.timedelta(hours=3)
# リクエストの時刻を指定します。
dt_obj_1 = dt_obj.strftime('%Y%m%dT%H%M%S') + 'Z'
# リクエストの日付を指定します。
dt_obj_2 = dt_obj.strftime('%Y%m%d')
# リクエストの有効期限を指定します。
expiration_time = dt_obj_plus_3h.strftime('%Y-%m-%dT%H:%M:%S.000Z')
# コールバックパラメータを Base64 でエンコードするために使用される関数を指定します。
def encode_callback(callback_params):
cb_str = json.dumps(callback_params).strip()
return oss2.compat.to_string(base64.b64encode(oss2.compat.to_bytes(cb_str)))
# コールバック構成を作成し、Base64 でエンコードします。
callback_config = {
"callbackUrl": "http://oss-demo.aliyuncs.com:23450/callback", # ローカルコールバックサーバーのアドレスを指定します。
"callbackBody": "bucket=${bucket}&object=${object}&etag=${etag}&size=${size}",
"callbackBodyType": "application/x-www-form-urlencoded"
}
encoded_callback = encode_callback(callback_config)
# ポリシーを作成し、署名を生成します。
policy = {
"expiration": expiration_time,
"conditions": [
["eq", "$success_action_status", "200"],
{"x-oss-signature-version": "OSS4-HMAC-SHA256"},
{"x-oss-credential": f"{temp_access_key_id}/{dt_obj_2}/cn-hangzhou/oss/aliyun_v4_request"},
{"x-oss-security-token": security_token},
{"x-oss-date": dt_obj_1},
]
}
policy_str = json.dumps(policy).strip()
# ステップ 2: 署名する文字列を作成します。
stringToSign = base64.b64encode(policy_str.encode()).decode()
# ステップ 3: 署名キーを計算します。
dateKey = hmacsha256(("aliyun_v4" + temp_access_key_secret).encode(), dt_obj_2)
dateRegionKey = hmacsha256(dateKey, "cn-hangzhou")
dateRegionServiceKey = hmacsha256(dateRegionKey, "oss")
signingKey = hmacsha256(dateRegionServiceKey, "aliyun_v4_request")
# ステップ 4: 署名を計算します。
result = hmacsha256(signingKey, stringToSign)
signature = result.hex()
# データを返します。
response_data = {
'policy': stringToSign, // フォームフィールド。
'x_oss_signature_version': "OSS4-HMAC-SHA256", // 署名バージョンと署名の計算に使用されるアルゴリズム。値を OSS4-HMAC-SHA256 に設定します。
'x_oss_credential': f"{temp_access_key_id}/{dt_obj_2}/cn-hangzhou/oss/aliyun_v4_request", // 派生キーに関する情報を指定するために使用されるパラメータセット。
'x_oss_date': dt_obj_1, // リクエスト時刻。
'signature': signature, // 署名の説明。
'host': host,
'dir': upload_dir,
'security_token': security_token, // セキュリティトークン。
'callback': encoded_callback // Base64 エンコードされたコールバック構成を返します。
}
return jsonify(response_data)
if __name__ == "__main__":
app.run(host="0.0.0.0", port=8000)Callback パラメータは、JSON 形式の複数のフィールドを含む Base64 エンコードされた文字列です。コールバックパラメータを構築するには、コールバックリクエストの送信先サーバーの URL (callbackUrl) とコールバックリクエストのコンテンツ (callbackBody) を指定する必要があります。
{"callbackUrl":"http://oss-demo.aliyuncs.com:23450",
"callbackBody":"filename=${object}&size=${size}&mimeType=${mimeType}&height=${imageInfo.height}&width=${imageInfo.width}",
"callbackBodyType":"application/x-www-form-urlencoded"}パラメータ | 説明 |
callbackUrl | OSS がリクエストを送信するアプリケーションサーバーの URL。 |
callbackBody | OSS がアプリケーションサーバーに送信するコンテンツ。画像以外のオブジェクトをアップロードする場合、コンテンツはオブジェクト名、サイズ、タイプにすることができます。画像をアップロードする場合、コンテンツは画像の高さ、幅にすることができます。 |
callbackBodyType | リクエストのコンテンツタイプ。 有効な値:
|
上記の例で使用されているコールバックメソッドは、参考用としてのみ提供されています。サーバーコードを変更することで、コールバックメソッドを構成できます。詳細については、「コールバック」をご参照ください。
Go
次のコマンドを実行して、依存関係をインストールします。
go get -u github.com/aliyun/credentials-go
go mod tidy次のサンプルコードは、STS から一時的なアクセス認証情報を取得し、オブジェクトのアップロードに使用できる署名を計算し、アップロードコールバックを構成する方法の例を示しています。
package main
import (
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"encoding/hex"
"encoding/json"
"fmt"
"io"
"hash"
"log"
"net/http"
"os"
"time"
"github.com/aliyun/credentials-go/credentials"
)
// グローバル変数を指定します。
var (
region string
bucketName string
product = "oss"
)
// 生成されたフォームデータを格納するために PolicyToken 構造体を使用します。
type PolicyToken struct {
Policy string `json:"policy"`
SecurityToken string `json:"security_token"`
SignatureVersion string `json:"x_oss_signature_version"`
Credential string `json:"x_oss_credential"`
Date string `json:"x_oss_date"`
Signature string `json:"signature"`
Host string `json:"host"`
Dir string `json:"dir"`
Callback string `json:"callback"`
}
type CallbackParam struct{
CallbackUrl string `json:"callbackUrl"`
CallbackBody string `json:"callbackBody"`
CallbackBodyType string `json:"callbackBodyType"`
}
func main() {
// デフォルトの IP とポートの文字列を指定します。
strIPPort := ":8080"
if len(os.Args) == 3 {
strIPPort = fmt.Sprintf("%s:%s", os.Args[1], os.Args[2])
} else if len(os.Args) != 1 {
fmt.Println("Usage : go run test1.go ")
fmt.Println("Usage : go run test1.go ip port ")
fmt.Println("Example : go run test1.go 11.22.**.** 80 ")
fmt.Println("Example : go run test1.go 0.0.0.0 8080 ")
fmt.Println("")
os.Exit(0)
}
// サーバーの IP アドレスとポートを表示します。
fmt.Printf("server is running on %s \n", strIPPort)
// ルートパスのリクエストを処理する関数を登録します。
http.HandleFunc("/", handlerRequest)
// 署名を取得するために開始されたリクエストを処理する関数を登録します。
http.HandleFunc("/get_post_signature_for_oss_upload", handleGetPostSignature)
// HTTP サーバーを起動します。
err := http.ListenAndServe(strIPPort, nil)
if err != nil {
strError := fmt.Sprintf("http.ListenAndServe failed : %s \n", err.Error())
panic(strError)
}
}
// handlerRequest 関数を使用して、ルートパスのリクエストを処理します。
func handlerRequest(w http.ResponseWriter, r *http.Request) {
if r.Method == "GET" {
http.ServeFile(w, r, "templates/index.html")
return
}
http.NotFound(w, r)
}
// handleGetPostSignature 関数を使用して、署名を取得するために開始されたリクエストを処理します。
func handleGetPostSignature(w http.ResponseWriter, r *http.Request) {
if r.Method == "GET" {
response := getPolicyToken()
w.Header().Set("Content-Type", "application/json")
w.Header().Set("Access-Control-Allow-Origin", "*") // クロスオリジンリクエストを許可します。
w.Write([]byte(response))
return
}
http.NotFound(w, r)
}
// getPolicyToken 関数を使用して、オブジェクトのアップロードに必要な署名とアクセス認証情報を生成します。
func getPolicyToken() string {
// バケットが配置されているリージョンを指定します。
region = "cn-hangzhou"
// バケットの名前を指定します。
bucketName = "examplebucket"
// オブジェクトをアップロードするバケットを指定します。
host := fmt.Sprintf("https://%s.oss-%s.aliyuncs.com", bucketName, region)
// オブジェクトをアップロードするディレクトリを指定します。
dir := "user-dir"
// アップロードコールバックリクエストの送信先サーバーの URL を指定します。IP アドレスとポート番号を実際の値に置き換えます。
callbackUrl := "http://oss-demo.aliyuncs.com:23450/callback";
config := new(credentials.Config).
SetType("ram_role_arn").
SetAccessKeyId(os.Getenv("OSS_ACCESS_KEY_ID")).
SetAccessKeySecret(os.Getenv("OSS_ACCESS_KEY_SECRET")).
SetRoleArn(os.Getenv("OSS_STS_ROLE_ARN")).
SetRoleSessionName("Role_Session_Name").
SetPolicy("").
SetRoleSessionExpiration(3600)
// 構成に基づいて認証情報プロバイダーを作成します。
provider, err := credentials.NewCredential(config)
if err != nil {
log.Fatalf("NewCredential fail, err:%v", err)
}
// 認証情報プロバイダーからアクセス認証情報を取得します。
cred, err := provider.GetCredential()
if err != nil {
log.Fatalf("GetCredential fail, err:%v", err)
}
// ポリシーを作成します。
utcTime := time.Now().UTC()
date := utcTime.Format("20060102")
expiration := utcTime.Add(1 * time.Hour)
policyMap := map[string]any{
"expiration": expiration.Format("2006-01-02T15:04:05.000Z"),
"conditions": []any{
map[string]string{"bucket": bucketName},
map[string]string{"x-oss-signature-version": "OSS4-HMAC-SHA256"},
map[string]string{"x-oss-credential": fmt.Sprintf("%v/%v/%v/%v/aliyun_v4_request", *cred.AccessKeyId, date, region, product)},
map[string]string{"x-oss-date": utcTime.Format("20060102T150405Z")},
map[string]string{"x-oss-security-token": *cred.SecurityToken},
},
}
// ポリシーの形式を JSON に変換します。
policy, err := json.Marshal(policyMap)
if err != nil {
log.Fatalf("json.Marshal fail, err:%v", err)
}
// 署名対象の文字列を作成します。
stringToSign := base64.StdEncoding.EncodeToString([]byte(policy))
hmacHash := func() hash.Hash { return sha256.New() }
// 署名キーを作成します。
signingKey := "aliyun_v4" + *cred.AccessKeySecret
h1 := hmac.New(hmacHash, []byte(signingKey))
io.WriteString(h1, date)
h1Key := h1.Sum(nil)
h2 := hmac.New(hmacHash, h1Key)
io.WriteString(h2, region)
h2Key := h2.Sum(nil)
h3 := hmac.New(hmacHash, h2Key)
io.WriteString(h3, product)
h3Key := h3.Sum(nil)
h4 := hmac.New(hmacHash, h3Key)
io.WriteString(h4, "aliyun_v4_request")
h4Key := h4.Sum(nil)
// 署名を生成します。
h := hmac.New(hmacHash, h4Key)
io.WriteString(h, stringToSign)
signature := hex.EncodeToString(h.Sum(nil))
var callbackParam CallbackParam
callbackParam.CallbackUrl = callbackUrl
callbackParam.CallbackBody = "filename=${object}&size=${size}&mimeType=${mimeType}&height=${imageInfo.height}&width=${imageInfo.width}"
callbackParam.CallbackBodyType = "application/x-www-form-urlencoded"
callback_str,err:=json.Marshal(callbackParam)
if err != nil {
fmt.Println("callback json err:", err)
}
callbackBase64 := base64.StdEncoding.EncodeToString(callback_str)
// フロントエンドにデータを返すために使用されるフォームを作成します。
policyToken := PolicyToken{
Policy: stringToSign,
SecurityToken: *cred.SecurityToken,
SignatureVersion: "OSS4-HMAC-SHA256",
Credential: fmt.Sprintf("%v/%v/%v/%v/aliyun_v4_request", *cred.AccessKeyId, date, region, product),
Date: utcTime.UTC().Format("20060102T150405Z"),
Signature: signature,
Host: host, // オブジェクトがアップロードされるバケットを返します。
Dir: dir, // オブジェクトがアップロードされるディレクトリを返します。
Callback: callbackBase64, // アップロードコールバックパラメータを返します。
}
response, err := json.Marshal(policyToken)
if err != nil {
fmt.Println("json err:", err)
}
return string(response)
}Node.js
次のコマンドを実行して、依存関係をインストールします。
npm install ali-oss
npm install @alicloud/credentials
npm install express次のサンプルコードは、STS から一時的なアクセス認証情報を取得し、オブジェクトのアップロードに使用できる署名を計算し、アップロードコールバックを構成する方法の例を示しています。
const express = require('express');
const OSS = require('ali-oss');
const { STS } = require('ali-oss');
const { getCredential } = require('ali-oss/lib/common/signUtils');
const { getStandardRegion } = require('ali-oss/lib/common/utils/getStandardRegion');
const { policy2Str } = require('ali-oss/lib/common/utils/policy2Str');
const app = express();
const PORT=process.env.PORT || 8000; // ポート番号を指定します。
// 静的ファイルが格納されているディレクトリを指定します。
app.use(express.static('templates'));
const GenerateSignature = async () => {
// STSClient インスタンスを初期化します。
let sts = new STS({
accessKeyId: process.env.OSS_ACCESS_KEY_ID, // 環境変数から RAM ユーザーの AccessKey ID を取得します。
accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET // 環境変数から RAM ユーザーの AccessKey シークレットを取得します。
});
// assumeRole オペレーションを呼び出して、STS から一時的なアクセス認証情報を取得します。
const result=await sts.assumeRole(process.env.OSS_STS_ROLE_ARN, ', '3600', 'yourRoleSessionName'); // 環境変数から RAM ロールの ARN を取得し、一時的なアクセス認証情報の有効期間を 3600 秒に設定し、ロールセッション名を yourRoleSessionName に設定します。
// 一時的なアクセス認証情報から AccessKeyId、AccessKeySecret、および SecurityToken パラメータの値を抽出します。
const accessKeyId = result.credentials.AccessKeyId;
const accessKeySecret = result.credentials.AccessKeySecret;
const securityToken = result.credentials.SecurityToken;
// OSSClient インスタンスを初期化します。
const client = new OSS({
bucket: 'examplebucket', // examplebucket を実際のバケット名に置き換えます。
region: 'cn-hangzhou', // cn-hangzhou をバケットが配置されているリージョンに置き換えます。
accessKeyId,
accessKeySecret,
stsToken: securityToken,
refreshSTSTokenInterval: 0,
refreshSTSToken: async () => {
const { accessKeyId, accessKeySecret, securityToken } = await client.getCredential();
return { accessKeyId, accessKeySecret, stsToken: securityToken };
},
});
// フォームデータマップを作成します。
const formData = new Map();
// 署名の有効期限を現在の時刻から 10 分後に設定します。
const date = new Date();
const expirationDate = new Date(date);
expirationDate.setMinutes(date.getMinutes() + 10);
// 日付を ISO 8601 標準に準拠した UTC 時間文字列にフォーマットします。
function padTo2Digits(num) {
return num.toString().padStart(2, '0');
}
function formatDateToUTC(date) {
return (
date.getUTCFullYear() +
padTo2Digits(date.getUTCMonth() + 1) +
padTo2Digits(date.getUTCDate()) +
'T' +
padTo2Digits(date.getUTCHours()) +
padTo2Digits(date.getUTCMinutes()) +
padTo2Digits(date.getUTCSeconds()) +
'Z'
);
}
const formattedDate = formatDateToUTC(expirationDate);
// アップロードコールバックリクエストの送信先のアプリケーションサーバーの URL を指定します。この URL は、アプリケーションサーバーと OSS 間の通信に使用されます。オブジェクトをアップロードした後、OSS はこの URL を使用してアップロード情報をアプリケーションサーバーに送信します。たとえば、callbackUrl を https://oss-demo.aliyuncs.com:23450 に設定できます。
// x-oss-credential を生成し、フォームデータを指定します。
const credential = getCredential(formattedDate.split('T')[0], getStandardRegion(client.options.region), client.options.accessKeyId);
formData.set('x_oss_date', formattedDate);
formData.set('x_oss_credential', credential);
formData.set('x_oss_signature_version', 'OSS4-HMAC-SHA256');
// ポリシーを作成します。
// 次のポリシーフォームフィールドでは、必須フィールドのみが指定されています。
const policy = {
expiration: expirationDate.toISOString(),
conditions: [
{ 'bucket': 'examplebucket' }, // examplebucket を実際のバケット名に置き換えます。
{ 'x-oss-credential': credential },
{ 'x-oss-signature-version': 'OSS4-HMAC-SHA256' },
{ 'x-oss-date': formattedDate },
],
};
// セキュリティトークンが存在する場合は、ポリシーとフォームデータに追加します。
if (client.options.stsToken) {
policy.conditions.push({ 'x-oss-security-token': client.options.stsToken });
formData.set('security_token', client.options.stsToken);
}
// 署名を生成し、フォームデータを指定します。
const signature = client.signPostObjectPolicyV4(policy, date);
formData.set('policy', Buffer.from(policy2Str(policy), 'utf8').toString('base64'));
formData.set('signature', signature);
const callback = {
callbackUrl: 'http://oss-demo.aliyuncs.com:23450/callback',// コールバックリクエストを受信するコールバックサーバーのアドレスを指定します。例: http://oss-demo.aliyuncs.com:23450/callback。
callbackBody:// コールバックリクエストに含めるコンテンツ (アップロードされたオブジェクトの ETag や mimeType など) を指定します。
"filename=${object}&size=${size}&mimeType=${mimeType}&height=${imageInfo.height}&width=${imageInfo.width}",
callbackBodyType: "application/x-www-form-urlencoded",// コールバックのコンテンツタイプを指定します。
};
// データをフォームで返します。
return {
host: `http://${client.options.bucket}.oss-${client.options.region}.aliyuncs.com`,
policy: Buffer.from(policy2Str(policy), 'utf8').toString('base64'),
x_oss_signature_version: 'OSS4-HMAC-SHA256',
x_oss_credential: credential,
x_oss_date: formattedDate,
signature: signature,
dir: 'user-dir', // OSS にアップロードするオブジェクトの名前にプレフィックスを指定します。
callback: Buffer.from(JSON.stringify(callback)).toString("base64"),// Buffer.from を使用して Base64 エンコードされた JSON。
security_token: client.options.stsToken
};
};
app.get('/get_post_signature_for_oss_upload', async (req, res) => {
try {
const result = await GenerateSignature();
res.json(result); // 生成された署名データを返します。
} catch (error) {
console.error('署名の生成中にエラーが発生しました:', error);
res.status(500).send('署名の生成中にエラーが発生しました');
}
});
app.listen(PORT, () => {
console.log(`サーバーは http://127.0.0.1:${PORT} で実行されています`);
});PHP
次のコマンドを実行して、依存関係をインストールします。
composer install次のサンプルコードは、STS から一時的なアクセス認証情報を取得し、オブジェクトのアップロードに使用できる署名を計算し、アップロードコールバックを構成する方法の例を示しています。
<?php
// Alibaba Cloud SDK を使用します。
require_once __DIR__ . '/vendor/autoload.php';
use AlibabaCloud\Client\AlibabaCloud;
use AlibabaCloud\Client\Exception\ClientException;
use AlibabaCloud\Client\Exception\ServerException;
use AlibabaCloud\Sts\Sts;
// エラーの表示を無効にします。
ini_set('display_errors', '0');
$bucket = 'examplebucket'; // examplebucket をバケット名に置き換えます。
$region_id = 'cn-hangzhou'; // cn-hangzhou をバケットが配置されているリージョンに置き換えます。
$host = 'http://examplebucket.oss-cn-hangzhou.aliyuncs.com'; // http://examplebucket.oss-cn-hangzhou.aliyuncs.com をバケットのドメイン名に置き換えます。
$expire_time = 3600; // 有効期間を秒単位で指定します。
$upload_dir = 'user-dir'; // OSS にアップロードするオブジェクトの名前にプレフィックスを指定します。
// $callbackUrl をコールバックサーバーの URL に設定します。IP アドレスとポート番号を実際の情報に置き換えます。
$callbackUrl = 'http://oss-demo.aliyuncs.com:23450/callback';
// HMAC-SHA256 値を計算します。
function hmacsha256($key, $data) {
return hash_hmac('sha256', $data, $key, true);
}
// 署名を取得するために開始されたリクエストを処理します。
if ($_SERVER['REQUEST_METHOD'] === 'GET' && $_SERVER['REQUEST_URI'] === '/get_post_signature_for_oss_upload') {
AlibabaCloud::accessKeyClient(getenv('OSS_ACCESS_KEY_ID'), getenv('OSS_ACCESS_KEY_SECRET'))
->regionId('cn-hangzhou')
->asDefaultClient();
// STS から一時的なアクセス認証情報を取得するためのリクエストを作成します。
$request = Sts::v20150401()->assumeRole();
// STS リクエストを開始し、結果を取得します。
// <YOUR_ROLE_SESSION_NAME> をカスタムセッション名 (例: oss-role-session) に置き換えます。
// <YOUR_ROLE_ARN> を、指定されたバケットにオブジェクトをアップロードする権限を持つ RAM ロールの ARN に置き換えます。
$result = $request
->withRoleSessionName('oss-role-session')
->withDurationSeconds(3600)
->withRoleArn(getenv('OSS_STS_ROLE_ARN')) // OSS_STS_ROLE_ARN を RAM ロールの ARN に置き換えます。
->request();
// STS リクエストへのレスポンスの認証情報を取得します。
$tokenData = $result->get('Credentials');
// 返された結果から JSON データを構築します。
$tempAccessKeyId = $tokenData['AccessKeyId'];
$tempAccessKeySecret = $tokenData['AccessKeySecret'];
$securityToken = $tokenData['SecurityToken'];
$now = time();
$dtObj = gmdate('Ymd\THis\Z', $now);
$dtObj1 = gmdate('Ymd', $now);
$dtObjPlus3h = gmdate('Y-m-d\TH:i:s.u\Z', strtotime('+3 hours', $now));
// ポリシーを作成します。
$policy = [
"expiration" => $dtObjPlus3h,
"conditions" => [
["x-oss-signature-version" => "OSS4-HMAC-SHA256"],
["x-oss-credential" => "{$tempAccessKeyId}/{$dtObj1}/cn-hangzhou/oss/aliyun_v4_request"],
["x-oss-security-token" => $securityToken],
["x-oss-date" => $dtObj],
]
];
$policyStr = json_encode($policy);
// 署名対象の文字列を作成します。
$stringToSign = base64_encode($policyStr);
// 署名キーを計算します。
$dateKey = hmacsha256(('aliyun_v4' . $tempAccessKeySecret), $dtObj1);
$dateRegionKey = hmacsha256($dateKey, 'cn-hangzhou');
$dateRegionServiceKey = hmacsha256($dateRegionKey, 'oss');
$signingKey = hmacsha256($dateRegionServiceKey, 'aliyun_v4_request');
// 署名を計算します。
$result = hmacsha256($signingKey, $stringToSign);
$signature = bin2hex($result);
$callback_param = array(
'callbackUrl' => $callbackUrl,
'callbackBody' => 'filename=${object}&size=${size}&mimeType=${mimeType}&height=${imageInfo.height}&width=${imageInfo.width}',
'callbackBodyType' => "application/x-www-form-urlencoded"
);
$callback_string = json_encode($callback_param);
$base64_callback_body = base64_encode($callback_string);
// 署名データを返します。
$responseData = [
'policy' => $stringToSign,
'x_oss_signature_version' => "OSS4-HMAC-SHA256",
'x_oss_credential' => "{$tempAccessKeyId}/{$dtObj1}/cn-hangzhou/oss/aliyun_v4_request",
'x_oss_date' => $dtObj,
'signature' => $signature,
'host' => $host,
'dir' => $upload_dir,
'security_token' => $securityToken,
'callback' => $base64_callback_body,
];
header('Content-Type: application/json');
echo json_encode($responseData);
exit;
}
// ホームページのルートを指定します。
if ($_SERVER['REQUEST_METHOD'] === 'GET' && $_SERVER['REQUEST_URI'] === '/') {
echo file_get_contents(__DIR__ . '/public/index.html');
exit;
}
// 他のルートを指定します。
http_response_code(404);
echo json_encode(['message' => 'Not Found']);
exit;
?>ステップ 3: Web クライアントを構成する
Web クライアントでフォームアップロードリクエストを作成して送信する
Web クライアントがサーバーから必要な情報を受信した後、その情報を使用して HTML フォームを作成するリクエストを構築できます。リクエストはファイルアップロードのために OSS に直接送信されます。
Web クライアントが受信したサンプルレスポンス
次の情報は、アプリケーションサーバーから Web クライアントに返されます。
{
"dir": "user-dirs",
"host": "http://examplebucket.oss-cn-hangzhou.aliyuncs.com",
"policy": "eyJl****",
"security_token": "CAIS****",
"signature": "9103****",
"x_oss_credential": "STS.NSpW****/20241127/cn-hangzhou/oss/aliyun_v4_request",
"x_oss_date": "20241127T060941Z",
"x_oss_signature_version": "OSS4-HMAC-SHA256"
"callback":"eyJjYWxsYmFja1VybCI6Imh0dHA6Ly9vc3MtZGVtby5hbGl5dW5jcy5jb206MjM0NTAiLAoiY2FsbGJhY2tCb2R5IjoiZmlsZW5hbWU9JHtvYmplY3R9JnNpemU9JHtzaXplfSZtaW1lVHlwZT0ke21pbWVUeXBlfSZoZWlnaHQ9JHtpbWFnZUluZm8uaGVpZ2h0fSZ3aWR0aD0ke2ltYWdlSW5mby53aWR0aH0iLAoiY2FsbGJhY2tCb2R5VHlwZSI6ImFwcGxpY2F0aW9uL3gtd3d3LWZvcm0tdXJsZW5jb2RlZCJ9"
}次の表に、本文に含まれるフィールドを示します。
フィールド | 説明 |
dir | アップロードするオブジェクトの名前に含まれるプレフィックス。 |
host | バケットのドメイン名。 |
policy | フォームアップロードのポリシー。詳細については、「POST ポリシー」をご参照ください。 |
security_token | STS から取得したセキュリティトークン。 |
signature | ポリシーの署名文字列。詳細については、「POST 署名」をご参照ください。 |
x_oss_credential | 派生キーを指定するために使用されるパラメータセット。 |
x_oss_date | リクエストが開始された時刻。時刻は ISO 8601 標準に従う必要があります。例: |
x_oss_signature_version | 署名バージョンと署名の計算に使用されるアルゴリズム。値を OSS4-HMAC-SHA256 に設定します。 |
callback | コールバックコンテンツ。 |
フォームリクエストには、ファイルコンテンツとサーバーから返されたパラメータが含まれています。
Web クライアントは、フォームリクエストを使用して OSS と直接通信し、ファイルをアップロードできます。
ファイルフォームフィールドを除き、各フォームフィールド (キーを含む) のサイズは 8 KB を超えることはできません。
デフォルトでは、アップロードするオブジェクトと同じ名前の既存のオブジェクトは上書きされます。既存のオブジェクトを上書きしたくない場合は、アップロードリクエストに x-oss-forbid-overwrite ヘッダーを含め、x-oss-forbid-overwrite ヘッダーを true に設定します。これにより、OSS の既存のオブジェクトと同じ名前のオブジェクトをアップロードすると、アップロードは失敗し、OSS は FileAlreadyExists エラーコードを返します。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>サーバーで署名を生成して OSS にファイルをアップロードする</title>
</head>
<body>
<div class="container">
<form>
<div class="mb-3">
<label for="file" class="form-label">ファイルを選択:</label>
<input type="file" class="form-control" id="file" name="file" required />
</div>
<button type="submit" class="btn btn-primary">アップロード</button>
</form>
<div id="callback-info" class="mt-3" style="display: none;">
<h4>コールバック情報:</h4>
<pre id="callback-content"></pre>
</div>
</div>
<script type="text/javascript">
document.addEventListener('DOMContentLoaded', function () {
const form = document.querySelector("form");
const fileInput = document.querySelector("#file");
const callbackInfo = document.querySelector("#callback-info");
const callbackContent = document.querySelector("#callback-content");
form.addEventListener("submit", (event) => {
event.preventDefault();
const file = fileInput.files[0];
if (!file) {
alert('アップロードするオブジェクトを選択してください。');
return;
}
const filename = file.name;
fetch("/get_post_signature_for_oss_upload", { method: "GET" })
.then((response) => {
if (!response.ok) {
throw new Error("署名の取得に失敗しました");
}
return response.json();
})
.then((data) => {
let formData = new FormData();
formData.append("success_action_status", "200");
formData.append("policy", data.policy);
formData.append("x-oss-signature", data.signature);
formData.append("x-oss-signature-version", "OSS4-HMAC-SHA256");
formData.append("x-oss-credential", data.x_oss_credential);
formData.append("x-oss-date", data.x_oss_date);
formData.append("key", data.dir + file.name); // ファイル名。
formData.append("x-oss-security-token", data.security_token);
formData.append("callback", data.callback); // コールバックパラメータを指定します。
formData.append("file", file); // 最後のフォームフィールドは「file」である必要があります。
return fetch(data.host, {
method: "POST",
body: formData
});
})
.then((response) => {
if (response.ok) {
console.log("アップロードされました");
alert("オブジェクトがアップロードされました");
return response.json(); // コールバック情報を解析します。
} else {
console.log("アップロードに失敗しました", response);
alert("オブジェクトのアップロードに失敗しました。オブジェクトを再アップロードしてみてください");
}
})
.then((callbackData) => {
if (callbackData) {
callbackContent.textContent = JSON.stringify(callbackData, null, 2);
callbackInfo.style.display = "block";
}
})
.catch((error) => {
console.error("エラーが発生しました:", error);
});
});
});
</script>
</body>
</html>HTML フォームには、ファイル入力ボックスと [送信] アイコンが含まれています。アップロードするファイルを選択して、フォームを送信できます。
フォームを送信すると、デフォルトのフォーム送信は JavaScript コードによってブロックされ、アップロードに必要な署名情報は AJAX (Asynchronous JavaScript and XML) リクエストを使用してサーバーから取得されます。
署名情報を取得した後、必要なすべてのフォームフィールドを含む
FormDataオブジェクトを構築します。fetchメソッドを使用して、OSS サービスの URL に POST リクエストを送信し、オブジェクトをアップロードできます。
ファイルがアップロードされると、「ファイルがアップロードされました」というメッセージが表示されます。ファイルのアップロードに失敗すると、エラーメッセージが表示されます。対応するコールバック情報は、フロントエンドページに返されます。
結果を確認する
上記の手順を完了すると、アプリケーションサーバーにアクセスして署名を生成し、Web クライアントから OSS にオブジェクトをアップロードできます。
ブラウザにアプリケーションサーバーの URL を入力し、アップロードするオブジェクトを選択して、[アップロード] アイコンをクリックしてオブジェクトをアップロードします。
バケット ページで、アップロードされたオブジェクトを格納するために作成したバケットの名前をクリックします。表示されるページで、Web クライアントからアップロードしたオブジェクトを表示します。
リソースを解放する
Web アプリケーションを構築するために、ECS インスタンス、OSS バケット、RAM ユーザー、および RAM ロールを作成しました。オブジェクトを OSS に正常にアップロードした後、不要な料金を防ぎ、関連するセキュリティリスクを排除するために、上記のリソースを解放できます。
ECS インスタンスを解放する
作成した ECS インスタンスが不要になった場合は、インスタンスを解放できます。ECS インスタンスが解放されると、インスタンスの課金は停止し、インスタンス上のデータは失われ、復元できなくなります。手順:
ECS コンソール の インスタンス ページに移動し、リージョンとインスタンス ID に基づいて ECS インスタンスを見つけ、ECS コンソール
[操作] 列の アイコンをクリックします。[インスタンスステータス] > [解放] を選択します。

[解放] ダイアログボックスで、[解放モード] を [今すぐ解放] に設定し、[次へ] をクリックします。
解放する関連リソースを確認し、データリスクに関する注意事項を読み、「解放するインスタンスとそれに関連付けられたリソースを認識しており、データリスクを理解しています」を選択して、[OK] をクリックします。
ECS インスタンスが解放されると、インスタンスのシステムディスクが解放されます。インスタンスにパブリック IP アドレスが割り当てられている場合、その IP アドレスも解放されます。
ECS インスタンスが解放されても、関連付けられているセキュリティグループ、vSwitch、および VPC は解放されません。セキュリティグループ、vSwitch、または VPC に対しては課金されません。ビジネス要件に基づいて、保持または解放できます。
EIP が ECS インスタンスに関連付けられている場合、インスタンスが解放されても EIP は保持されます。EIP に対しては課金されます。ビジネス要件に基づいて、EIP を保持または解放できます。
バケットを削除する
OSS コンソール にログインします。
左側のナビゲーションウィンドウで、バケット をクリックします。[バケットリスト] ページで、削除するバケットの名前をクリックします。
バケット内のすべてのオブジェクトを削除してから、バケットを削除します。
左側のナビゲーションツリーで、バケットの削除 をクリックします。[バケットの削除] ページで、画面の指示に従ってバケットを削除します。
RAM ユーザーを削除する
管理者権限を持つ RAM ユーザーとして RAM コンソール にログインします。
左側のナビゲーションウィンドウで、[Identities] > [Users] を選択します。
[ユーザー] ページで、削除する RAM ユーザーを見つけ、[削除][操作] 列の をクリックします。
複数の RAM ユーザーを選択し、RAM ユーザーリストの下にある [ユーザーの削除] をクリックして、選択したすべての RAM ユーザーを同時にゴミ箱に移動することもできます。
[ユーザーの削除] ダイアログボックスで、削除操作の影響に関するステートメントを読み、RAM ユーザーの名前を入力して、[ゴミ箱に移動] をクリックします。
RAM ロールを削除する
管理者権限を持つ RAM ユーザーとして RAM コンソール にログインします。
左側のナビゲーションウィンドウで、[ID] > [ロール] を選択します。
[ロール] ページで、削除する RAM ロールを見つけ、[ロールの削除][操作] 列の をクリックします。
[ロールの削除] ダイアログボックスで、RAM ロールの名前を入力し、[ロールの削除] をクリックします。
説明ポリシーが RAM ロールにアタッチされている場合、RAM ロールを削除するとポリシーはデタッチされます。
FAQ
一度に複数のオブジェクトを OSS にアップロードするにはどうすればよいですか?
OSS は、一度に複数のオブジェクトをアップロードするための API オペレーションを提供していません。一度に複数のオブジェクトを OSS にアップロードする場合は、単一のオブジェクトをアップロードする手順を繰り返し実行できます。
サーバーから署名情報を取得し、アップロードコールバックを構成するときに、コールバックリクエストのヘッダーを指定できますか?
いいえ。カスタムコールバックパラメータ、つまりコールバックリクエストの本文のみを指定できます。ただし、コールバック URL への OSS コールバックリクエストに含まれるヘッダーを指定することはできません。