サーバーで生成した署名を用いたPostObject 操作を使用して、Web クライアントから OSS へオブジェクトを直接アップロードします。この方法では、アップロードコールバックと、アップロードを制御するポリシーに対応しています。
ソリューションの概要
このワークフローは、3 つのステップで構成されています。
このプロセスでは、アプリケーションサーバーの AccessKey ペアが公開されるのを防ぐために、一時的なアクセス認証情報を使用します。
-
OSS の設定:バケットを作成し、Web クライアントからのクロスオリジンリクエストを許可するように、オリジン間リソース共有 (CORS) ルールを設定します。
-
サーバーの設定:アクセス認証情報と、バケット名、ディレクトリパス、有効期限などの条件を含むポリシーを使用して、有効期間限定の署名を生成します。
-
Web クライアントの設定:OSS にオブジェクトを直接アップロードするための HTML フォームを作成します。OSS はコールバック設定を解析し、POST コールバックリクエストをアプリケーションサーバーに送信します。
サンプルプロジェクト
手順
ステップ 1: OSS の設定
ステップ 1:バケットの作成
ウェブクライアントからアップロードされたファイルを保存するために、バケットを作成します。
-
OSS コンソールにログインします。
-
左側のナビゲーションペインで、バケットをクリックし、次にバケットの作成をクリックします。
-
バケットの作成 パネルで、[クイック作成] を選択し、以下のパラメーターを設定します。
パラメーター
値の例
[バケット名]
web-direct-upload-callback
[リージョン]
China (Hangzhou)
-
OK をクリックします。
ステップ 2: CORS ルールの設定
OSS バケットに CORS ルールを設定します。
-
[バケット] ページに移動し、ターゲットバケット名をクリックします。
-
クロスオリジンリソース共有の設定 タブで、ルールの作成 をクリックします。
-
ルールの作成 パネルで、次のように CORS ルールを設定します。
パラメーター
値の例
[ソース]
*
[許可されたメソッド]
POST、PUT、GET
[許可されたヘッダー]
*
-
OK をクリックします。
ステップ 2:サーバーの設定
すでにサーバーをお持ちの場合は、準備作業をスキップして、ユーザー権限に進んでください。
ECS インスタンスの作成
ステップ 1: ECS インスタンスの作成
カスタム起動 ページに移動し、次のリソースを設定します。
-
リージョンと課金方法の選択
-
課金方法を選択します。このトピックでは 従量課金 を使用します。
-
エンドユーザーに近いリージョンを選択します。このトピックでは China (Hangzhou) を使用します。
[課金方法] セクションで、[従量課金] を選択します。
-
-
VPC と vSwitch の作成
VPC と vSwitch を作成した後、ECS インスタンス作成ページに戻り、ページを更新してそれらを選択します。
説明VPC を作成する際に vSwitch を作成できます。
「仮想プライベートクラウドの作成」ページで、[名前]を
ProjectA-VPCに設定します。[IPv4 CIDR ブロック]には、[IPv4 CIDR ブロックを手動で入力]を選択し、192.168.0.0/16を入力します。[IPv6 CIDR ブロック]には、[IPv6 なし]を選択します。vSwitch セクションで、[名前] を
ProjectA-vSwitchに設定し、[アベイラビリティゾーン] で 杭州ゾーン H を選択し、[IPv4 CIDR ブロック] を192.168.10.0/24に設定して、[OK] をクリックします。
-
インスタンスタイプとイメージの選択
このチュートリアルでは、
ecs.e-c1m1.largeインスタンスタイプとAlibaba Cloud Linux 3.2104 LTS 64-bitパブリックイメージを使用します。[インスタンスタイプ] セクションの [すべての世代] タブで、
ecs.e-c1m1.largeインスタンスタイプを検索して選択します。 [イメージ] セクションの [パブリックイメージ] タブで、オペレーティングシステムに [Alibaba Cloud Linux] を、バージョンに [3.2104 LTS 64-bit] を選択します。
-
ストレージの設定
このチュートリアルでは、システムディスクのみが必要です。データディスクは不要です。
システムディスクでは、[ESSD] を選択します。容量を [40 GiB] に設定し、パフォーマンスレベルを [PL0 (ディスクあたりの最大 IOPS: 10,000)] に設定します。[インスタンスとともにリリース] チェックボックスにチェックを入れます。
-
パブリック IP アドレスの割り当て
このインスタンスにはインターネットアクセスが必要です。このチュートリアルでは、作成時にパブリック IP アドレスを割り当てます。または、作成後に EIP をクラウドリソースに関連付けることもできます。
説明-
パブリック IP アドレスがない場合、インターネット経由でインスタンスに接続したり、Web サービスのデプロイを検証したりすることはできません。
-
このチュートリアルでは トラフィック課金 を使用します。これは、アウトバウンドデータのみに課金する方式です。パブリック帯域幅の課金。
[ピーク帯域幅] を [5 Mbps] に設定します。
-
-
セキュリティグループの作成
セキュリティグループは、ECS インスタンスのインバウンドトラフィックとアウトバウンドトラフィックを制御します。インバウンドトラフィックを許可するために、次のポートを開放します。
ポート範囲: SSH (22)、RDP (3389)、HTTP (80)、HTTPS (443)
説明-
[ポート範囲] パラメーターは、ECS インスタンスで実行されるアプリケーションに必要なポートを指定します。
-
デフォルトでは、セキュリティグループはすべての IP アドレス (0.0.0.0/0) からのトラフィックを許可します。作成後、トラフィックを特定の IP 範囲に制限してください。セキュリティグループルールを変更する。
[セキュリティグループタイプ] では、[基本セキュリティグループ] を選択します。
-
-
キーペアの作成
-
キーペアを作成した後、ECS インスタンスに接続するために秘密鍵をダウンロードして保存します。インスタンス作成ページに戻り、ページを更新してキーペアを選択します。
-
rootユーザーは、すべてのシステム権限を持っています。rootでログインすると、セキュリティ上のリスクがあります。ログインユーザー名としてecs-userを使用してください。説明秘密鍵ファイルが自動的にダウンロードされます。ブラウザのダウンロード履歴から
.pemファイルを保存してください。[キーペアの作成] リンクをクリックして、新しいキーペアを作成します。 次に、[キーペア] ドロップダウンリストで、作成したばかりのキーペア (
ecs-testなど) を選択します。
-
-
ECS インスタンスの作成と確認
[注文の作成] をクリックし、次に コンソール をクリックして新しい ECS インスタンスを表示します。 次の情報を記録します:
-
インスタンス ID: インスタンスリストでインスタンスを見つけるために使用します。
-
リージョン: インスタンスリストでインスタンスを見つけるために使用します。
-
パブリック IP アドレス: デプロイした Web サービスにアクセスして検証するために使用します。
ECS コンソールのインスタンスリストで、それぞれの列でインスタンス ID、リージョン、パブリック IP アドレスを確認できます。
-
ステップ 2: ECS インスタンスへの接続
-
ECS コンソールの [インスタンス] ページで、リージョンと ID に基づいて作成したインスタンスを見つけ、アクション 列で 接続 をクリックします。
-
リモート接続 ダイアログボックスの ワークベンチ オプションで、今すぐサインイン をクリックします。
-
[インスタンスにログオン] ダイアログボックスで、[接続方法] を [ターミナル] に、[認証方法] を [SSH キーベースの認証] に設定します。キーペアの作成時にダウンロードした秘密キーファイルを入力またはアップロードし、[ログイン] をクリックします。これで、
ecs-userとして ECS インスタンスにログインしました。説明ブラウザーのダウンロード履歴で
.pem秘密鍵ファイルを確認してください。 -
ログオン成功後の出力例:
Welcome to Alibaba Cloud Elastic Compute Service ! Last login: Sun Sep 29 15:35:22 2024 from xxx [ecs-user@ixxx ~]$
ユーザー権限
アップロードの失敗を防ぐために、デプロイの前に RAM ユーザーを作成し、必要な権限を付与してください。
ステップ 1: RAM ユーザーの作成
RAM ユーザーを作成し、サーバーアプリケーションの長期的な認証情報としてその AccessKey を取得します。
-
Alibaba Cloud アカウントを使用するか、RAM 管理者として RAM コンソール にログインします。
-
ナビゲーションペインで、 [アイデンティティ] > [ユーザー] を選択します。
-
[ユーザーの作成] をクリックします。
-
[ログイン名] と [表示名] を入力します。
-
アクセスモード セクションで、 [プログラムによるアクセス] を選択し、 OK をクリックします。
RAM ユーザーの AccessKey Secret は、作成時に一度しか表示されず、後で取得することはできません。 必ず安全な場所に保管してください。
-
[操作] 列の [コピー] をクリックして、AccessKey (AccessKey ID と AccessKey Secret) を保存します。
ステップ 2: AssumeRole 権限の付与
RAM ユーザーに STS AssumeRole オペレーションを呼び出して一時的な認証情報を取得する権限を付与します。
-
ナビゲーションペインで、 [アイデンティティ] > [ユーザー] を選択します。
-
[ユーザー] ページで、対象の RAM ユーザーを見つけ、[操作] 列の [権限の追加] をクリックします。
-
[権限の追加] ページで、 AliyunSTSAssumeRoleAccess システムポリシーを選択します。
説明AliyunSTSAssumeRoleAccess ポリシーは、STS AssumeRole オペレーションを呼び出す権限を付与します。 これは、一時的な認証情報を通じて付与される Object Storage Service (OSS) のアクセス権限とは別です。
[リソーススコープ] を [アカウントレベル] に設定し、 [OK] をクリックします。
-
[権限付与の確認] をクリックします。
ステップ 3: RAM ロールの作成
Alibaba Cloud アカウント用に RAM ロールを作成し、その Alibaba Cloud リソースネーム (ARN) を取得します。
-
ナビゲーションペインで、 [アイデンティティ] > [ロール] を選択します。
-
[ロールの作成] をクリックします。 信頼できるエンティティタイプとして、 [Alibaba Cloud アカウント] を選択します。
-
[現在の Alibaba Cloud アカウント] を選択し、 OK をクリックします。
-
ロール名を入力し、 OK をクリックします。
-
RAM ロール管理ページで [コピー] をクリックして、ロールの ARN を保存します。
ステップ 4: ファイルアップロード用ポリシーの作成
RAM ロールが指定されたバケットにのみオブジェクトをアップロードできるよう制限するカスタムポリシーを作成します。
-
ナビゲーションペインで、 [権限] > [ポリシー] を選択します。
-
[ポリシーの作成] をクリックします。
-
[ポリシーの作成] ページで、 [JSON] タブをクリックします。 ポリシードキュメントで、
<BucketName>を、以前作成したバケット名web-direct-uploadに置き換えます。{ "Version": "1", "Statement": [ { "Effect": "Allow", "Action": "oss:PutObject", "Resource": "acs:oss:*:*:<BucketName>/*" } ] } -
ポリシーを設定した後、 OK をクリックします。
-
[ポリシーの作成] ダイアログボックスで、ポリシーの [名前] を入力し、 OK をクリックします。
ステップ 5: RAM ロールへの権限付与
カスタムポリシーを RAM ロールにアタッチします。
-
ナビゲーションペインで、 [アイデンティティ] > [ロール] を選択します。
-
[ロール] ページで、対象の RAM ロールを見つけ、[操作] 列の [権限の追加] をクリックします。
-
[権限の追加] ページで、 [カスタムポリシー] タブを選択し、作成したカスタムポリシーを選択します。
[リソーススコープ] を [アカウントレベル] に設定します。
-
OK をクリックします。
2. 認証情報と署名の取得
コードに認証情報をハードコーディングしないように、accessKeyId、accessKeySecret、roleArn を環境変数として設定します。
次の環境変数を追加します。
Linux
-
次のコマンドを実行して、環境変数の設定を
~/.bashrcファイルに追記します。echo "export OSS_ACCESS_KEY_ID='your-access-key-id'" >> ~/.bashrc echo "export OSS_ACCESS_KEY_SECRET='your-access-key-secret'" >> ~/.bashrc echo "export OSS_STS_ROLE_ARN='your-role-arn'" >> ~/.bashrc -
次のコマンドを実行して変更を適用します。
source ~/.bashrc -
次のコマンドを実行して、環境変数が設定されているかどうかを確認します。
echo $OSS_ACCESS_KEY_ID echo $OSS_ACCESS_KEY_SECRET echo $OSS_STS_ROLE_ARN
macOS
-
ターミナルで次のコマンドを実行して、デフォルトのシェルタイプを確認します。
echo $SHELL -
デフォルトのシェルタイプに応じた手順に従ってください。
Zsh
-
次のコマンドを実行して、環境変数の設定を
~/.zshrcファイルに追記します。echo "export OSS_ACCESS_KEY_ID='your-access-key-id'" >> ~/.zshrc echo "export OSS_ACCESS_KEY_SECRET='your-access-key-secret'" >> ~/.zshrc echo "export OSS_STS_ROLE_ARN='your-role-arn'" >> ~/.zshrc -
次のコマンドを実行して変更を適用します。
source ~/.zshrc -
次のコマンドを実行して、環境変数が設定されているかどうかを確認します。
echo $OSS_ACCESS_KEY_ID echo $OSS_ACCESS_KEY_SECRET echo $OSS_STS_ROLE_ARN
Bash
-
次のコマンドを実行して、環境変数の設定を
~/.bash_profileファイルに追記します。echo "export OSS_ACCESS_KEY_ID='your-access-key-id'" >> ~/.bash_profile echo "export OSS_ACCESS_KEY_SECRET='your-access-key-secret'" >> ~/.bash_profile echo "export OSS_STS_ROLE_ARN='your-role-arn'" >> ~/.bash_profile -
次のコマンドを実行して変更を適用します。
source ~/.bash_profile -
次のコマンドを実行して、環境変数が設定されているかどうかを確認します。
echo $OSS_ACCESS_KEY_ID echo $OSS_ACCESS_KEY_SECRET echo $OSS_STS_ROLE_ARN
-
Windows
-
コマンド プロンプトで次のコマンドを実行します。
setx OSS_ACCESS_KEY_ID "your-access-key-id" setx OSS_ACCESS_KEY_SECRET "your-access-key-secret" setx OSS_STS_ROLE_ARN "your-role-arn" -
新しいコマンド プロンプト ウィンドウを開きます。
-
新しいコマンド プロンプト ウィンドウで、次のコマンドを実行して環境変数が設定されているかどうかを確認します。
echo %OSS_ACCESS_KEY_ID% echo %OSS_ACCESS_KEY_SECRET% echo %OSS_STS_ROLE_ARN%
次のサンプルコードを使用して、サーバー上で 署名バージョン 4 (推奨) による POST 署名を計算します。利用可能なポリシー条件の一覧については、「ポリシーフォームフィールド」のトピックをご参照ください。
Java
Maven プロジェクトに、次の依存関係を追加します。
<!-- https://mvnrepository.com/artifact/com.aliyun/credentials-java -->
<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>
次のサンプルコードを使用して、サーバーで一時的な認証情報を取得し、POST 署名を計算し、アップロードコールバックを設定します。
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 {
// OSS の基本情報。バケット名、リージョン ID、ホストを実際の値に置き換えてください。
String bucket = "examplebucket";
String region = "cn-hangzhou";
String host = "http://examplebucket.oss-cn-hangzhou.aliyuncs.com";
// アップロードコールバックの URL。これはパブリック URL である必要があります。これは、アプリケーションサーバーと OSS 間の通信に使用されます。ファイルがアップロードされると、OSS はこの URL を介してアップロード情報をアプリケーションサーバーに送信します。
String callbackUrl = "http://oss-demo.aliyuncs.com:23450/callback"; // コールバックリクエストを受信するサーバーの URL。例: 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;
Instant instant = Instant.ofEpochSecond(expirationTime);
ZoneId zone = ZoneOffset.UTC;
ZonedDateTime zonedDateTime = instant.atZone(zone);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
String formattedDate = zonedDateTime.format(formatter);
return formattedDate;
}
// STS クライアントを初期化します。
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);
// `credentials` オブジェクトには、AccessKeyId、AccessKeySecret、およびセキュリティトークンが含まれます。
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);
}
// null が返されるのを避けるために、デフォルトのエラーレスポンスオブジェクトを返します。
AssumeRoleResponseBody.AssumeRoleResponseBodyCredentials defaultCredentials = new AssumeRoleResponseBody.AssumeRoleResponseBodyCredentials();
defaultCredentials.accessKeyId = "ERROR_ACCESS_KEY_ID";
defaultCredentials.accessKeySecret = "ERROR_ACCESS_KEY_SECRET";
defaultCredentials.securityToken = "ERROR_SECURITY_TOKEN";
return defaultCredentials;
}
@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;
// yyyyMMdd 形式の現在の日付を取得します。x-oss-credential フィールドで使用します。
ZonedDateTime today = ZonedDateTime.now().withZoneSameInstant(java.time.ZoneOffset.UTC);
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);
conditions.add(Arrays.asList("starts-with", "$key", upload_dir));
conditions.add(Arrays.asList("content-length-range", 1, 10240000));
conditions.add(Arrays.asList("eq", "$success_action_status", "200"));
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);
conditions.add(credentialCondition);
Map<String, String> securityTokenCondition = new HashMap<>();
securityTokenCondition.put("x-oss-security-token", securitytoken);
conditions.add(securityTokenCondition);
Map<String, String> dateCondition = new HashMap<>();
dateCondition.put("x-oss-date", x_oss_date);
conditions.add(dateCondition);
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("x_oss_signature_version", "OSS4-HMAC-SHA256");
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);
// PostObject 操作のため、Web クライアントにステータスコード 200 (OK) の ResponseEntity を返します。
return ResponseEntity.ok(response);
}
public static byte[] hmacsha256(byte[] key, String data) {
try {
// HMAC キー仕様を初期化し、アルゴリズムを HmacSHA256 に設定し、提供されたキーを使用します。
SecretKeySpec secretKeySpec = new SecretKeySpec(key, "HmacSHA256");
// Mac インスタンスを取得し、getInstance メソッドを使用して HmacSHA256 アルゴリズムを指定します。
Mac mac = Mac.getInstance("HmacSHA256");
// Mac オブジェクトをキーで初期化します。
mac.init(secretKeySpec);
// データの HMAC ハッシュを計算します。
byte[] hmacBytes = mac.doFinal(data.getBytes());
return hmacBytes;
} catch (Exception e) {
throw new RuntimeException("Failed to calculate HMAC-SHA256", e);
}
}
}
Python
次のコマンドを実行して依存関係をインストールします。
pip install flask
pip install alibabacloud_tea_openapi alibabacloud_sts20150401 alibabacloud_credentials
次のサンプルコードを使用して、STS から一時的な認証情報を取得し、アップロードポリシーを構築し、POST 署名を計算し、コールバックを設定します。
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"Failed to calculate HMAC-SHA256 due to {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
)
# STS クライアントを作成し、一時的な認証情報を取得します。
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", # コールバックサーバーの URL。
"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": [
{"bucket": bucket},
["starts-with", "$key", upload_dir],
["content-length-range", 1, 10240000],
["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="127.0.0.1", port=8000) # 0.0.0.0 など、他のアドレスでリッスンする必要がある場合は、サーバーに認証メカニズムを追加する必要があります。
Node.js
次のコマンドを実行して依存関係をインストールします。
npm install ali-oss
npm install @alicloud/credentials
npm install express
次のサンプルコードを使用して、STS から一時的な認証情報を取得し、アップロードポリシーを構築し、POST 署名を計算し、コールバックを設定します。
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 () => {
// STS クライアントを初期化します。
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 を取得し、一時的なアクセス認証情報の有効期間を 3,600 秒に設定し、カスタムロールセッション名を指定します。
// 一時的なアクセス認証情報から AccessKeyId、AccessKeySecret、および SecurityToken を抽出します。
const accessKeyId = result.credentials.AccessKeyId;
const accessKeySecret = result.credentials.AccessKeySecret;
const securityToken = result.credentials.SecurityToken;
// OSS クライアントを初期化します。
const client = new OSS({
bucket: 'examplebucket', // 対象のバケット名に置き換えてください。
region: '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。これは、アプリケーションサーバーと 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' }, // 対象のバケット名に置き換えてください。
['starts-with', '$key', 'user-dir'],
['content-length-range', 1, 10240000],
['eq', '$success_action_status', '200'],
{ 'x-oss-credential': credential },
{ 'x-oss-signature-version': 'OSS4-HMAC-SHA256' },
{ 'x-oss-date': formattedDate },
],
};
// STS トークンが存在する場合は、ポリシーとフォームデータに追加します。
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',// コールバックリクエストを受信するサーバーの URL。例: http://oss-demo.aliyuncs.com:23450/callback。
callbackBody:// ファイルの ETag やリソースの MIME タイプなど、コールバックの内容。
"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 を使用して JSON オブジェクトを Base64 エンコードします。
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 generating signature:', error);
res.status(500).send('Error generating signature');
}
});
app.listen(PORT, () => {
console.log(`Server is running on http://127.0.0.1:${PORT}`); // 0.0.0.0 など、他のアドレスでリッスンする必要がある場合は、サーバーに認証メカニズムを追加する必要があります。
});
Go
次のコマンドを実行して依存関係をインストールします。
go get -u github.com/aliyun/credentials-go
go mod tidy
次のサンプルコードを使用して、STS から一時的な認証情報を取得し、アップロードポリシーを構築し、POST 署名を計算し、コールバックを設定します。
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)
}
// サーバーが実行されているアドレスとポートを出力します。
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 関数は、OSS アップロードに必要な署名と認証情報を生成します。
func getPolicyToken() string {
// バケットのリージョンを設定します。
region = "cn-hangzhou"
// バケット名を設定します。
bucketName = "examplebucket"
// OSS アップロードエンドポイントを設定します。
host := fmt.Sprintf("https://%s.oss-%s.aliyuncs.com", bucketName, region)
// アップロードディレクトリを設定します。
dir := "user-dir"
// callbackUrl は、アップロードコールバックを受信するサーバーの 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},
[]any{"starts-with", "$key", dir},
[]any{"content-length-range", 1, 10240000},
[]any{"eq", "$success_action_status", "200"},
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, // OSS アップロードエンドポイント。
Dir: dir, // アップロードディレクトリ。
Callback: callbackBase64, // アップロードコールバックパラメーター。
}
response, err := json.Marshal(policyToken)
if err != nil {
fmt.Println("json err:", err)
}
return string(response)
}
PHP
次のコマンドを実行して依存関係をインストールします。
composer install
次のサンプルコードを使用して、STS から一時的な認証情報を取得し、アップロードポリシーを構築し、POST 署名を計算し、コールバックを設定します。
<?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'; // バケット名に置き換えてください。
$region_id = 'cn-hangzhou'; // バケットのリージョンに置き換えてください。
$host = 'http://examplebucket.oss-cn-hangzhou.aliyuncs.com'; // バケットのドメイン名に置き換えてください。
$expire_time = 3600; // 有効期限 (秒単位)。
$upload_dir = 'user-dir'; // アップロードファイルのプレフィックス。
// $callbackUrl は、アップロードコールバックを受信するサーバーの URL です。実際の URL に合わせて IP アドレスとポートを置き換えてください。
$callbackUrl = 'http://oss-demo.aliyuncs.com:23450/callback';
// HMAC-SHA256 を計算します。
function hmacsha256($key, $data) {
return hash_hmac('sha256', $data, $key, true);
}
// POST 署名取得リクエストを処理します。
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 リクエストを開始し、結果を取得します。
// をカスタムセッション名 (例: oss-role-session) に設定してください。
// を、指定された OSS バケットにファイルをアップロードする権限を持つ RAM ロールの ARN に置き換えてください。
$result = $request
->withRoleSessionName('oss-role-session')
->withDurationSeconds(3600)
->withRoleArn(getenv('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" => [
["bucket" => $bucket],
["starts-with", '$key', $upload_dir],
["content-length-range", 1, 10240000],
["eq", '$success_action_status', '200'],
["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;
?>
callback パラメーターは、Base64 エンコードされた JSON 文字列です。これを構築するには、callbackUrl (コールバックリクエストを受信するサーバーの URL) と callbackBody (コールバックの内容) を指定します。
{"callbackUrl":"http://oss-demo.aliyuncs.com:23450/callback",
"callbackBody":"filename=${object}&size=${size}&mimeType=${mimeType}&height=${imageInfo.height}&width=${imageInfo.width}",
"callbackBodyType":"application/x-www-form-urlencoded"}
|
パラメーター |
説明 |
|
callbackUrl |
OSS からのコールバックを受信するアプリケーションサーバーの URL。 |
|
callbackBody |
OSS からアプリケーションサーバーに送信されるコールバックリクエストの内容。ファイルの名前、サイズ、MIME タイプ、または画像の高さと幅などを含めることができます。 |
|
callbackBodyType |
リクエストの 有効な値:
|
この例では、基本的なコールバック設定を示します。要件に基づいてカスタマイズしてください。詳細については、「コールバック」をご参照ください。
ステップ 3: Web クライアントの設定
Web クライアントのフォームアップロード
Web クライアントは、HTML フォームリクエストを構築して、ファイルを OSS に直接アップロードします。
レスポンスの例
アプリケーションサーバーは、次のレスポンスを 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 Policy」をご参照ください。 |
|
security_token |
セキュリティトークン。Web クライアントは、この値をフォームフィールド |
|
signature |
ポリシーから計算された署名。Web クライアントは、この値をフォームフィールド |
|
x_oss_credential |
派生キーのパラメーターを指定します。 |
|
x_oss_date |
ISO 8601 形式のリクエストタイムスタンプ。例: |
|
x_oss_signature_version |
署名バージョンとアルゴリズム。値は常に OSS4-HMAC-SHA256 です。 |
|
callback |
コールバックリクエストのボディ。 |
-
フォームリクエストには、ファイルの内容とアプリケーションサーバーから受信したパラメーターが含まれます。
-
Web クライアントは、このデータを multipart/form-data POST リクエストとして OSS に直接送信します。
-
fileフォームフィールドを除き、keyを含む他のすべてのフォームフィールドのサイズは 8 KB を超えることはできません。 -
デフォルトでは、同じ名前の既存のオブジェクトはアップロード時に上書きされます。これを防ぐには、アップロードリクエストに
x-oss-forbid-overwriteヘッダーを含め、その値をtrueに設定します。同じ名前のオブジェクトが既に存在する場合、アップロードは失敗し、OSS はFileAlreadyExistsエラーを返します。
<!DOCTYPE html>
<html lang="ja">
<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 リクエストをアプリケーションサーバーに送信して、必要な署名情報を取得します。
-
署名情報を取得した後、必要なすべてのフォームフィールドを含む
FormDataオブジェクトを構築します。 -
fetchメソッドを使用して OSS サービスの URL に POST リクエストを送信してオブジェクトをアップロードします。
アップロードが成功すると、「ファイルがアップロードされました」というメッセージとコールバック情報が表示されます。アップロードが失敗すると、エラーメッセージが表示されます。
結果の検証
デプロイメント後、アップロード機能をテストします。
-
ブラウザでサーバーアドレスにアクセスし、[ファイルを選択] ボタンをクリックしてファイルを選択してから、アップロードします。
-
[バケット] ページで、対象のバケットを見つけ、ファイルが正常にアップロードされたことを確認します。
リソースのクリーンアップ
継続的な課金を避けるために、このチュートリアルで作成したリソースを削除してください。
ECS インスタンスのリリース
インスタンスをリリースすると、課金が停止し、データが完全に削除されます。
-
ECS コンソールの インスタンスページに移動します。リージョンとインスタンス ID で対象の ECS インスタンスを見つけます。[アクション] 列で、
をクリックします。 -
ドロップダウンメニューで、[インスタンスステータス] セクションの [リリース] を選択します。
-
正しいインスタンスを選択したことを確認し、[今すぐリリース] を選択してから、[次へ] をクリックします。
-
リリースされる関連リソースを確認し、データリスクに同意します。次に、[OK] をクリックします。
-
システムディスクと割り当てられたパブリック IP アドレスは、インスタンスとともにリリースされます。
-
セキュリティグループ、vSwitch、VPC は、インスタンスとともにリリースされません。これらのリソースは無料であるため、ビジネスニーズに応じて削除できます。
-
EIP は、インスタンスとともにリリースされず、無料のリソースではありません。ビジネスニーズに応じて削除できます。
バケットの削除
-
OSS コンソールにログインします。
-
左側のナビゲーションペインで、バケット をクリックします。次に、目的のバケットの名前をクリックします。
-
バケット内のすべてのオブジェクトを削除します。
-
左側のナビゲーションペインで、バケットの削除 をクリックします。
RAM ユーザーの削除
-
RAM 管理者として RAM コンソールにログインします。
-
左側のナビゲーションペインで、アイデンティティ > [ユーザー] を選択します。
-
[ユーザー] ページで、削除する RAM ユーザーを見つけ、[アクション] 列の [削除] をクリックします。
または、複数の RAM ユーザーを一度に削除するには、対象のチェックボックスにチェックを入れ、リストの下部にある [ユーザーの削除] をクリックします。このアクションにより、ユーザーはごみ箱に移動されます。
-
[ユーザーの削除] ダイアログボックスで、削除による影響を確認し、確認として RAM ユーザー名を入力してから、[ごみ箱に移動] をクリックします。
RAM ロールの削除
-
RAM 管理者として RAM コンソールにログインします。
-
左側のナビゲーションペインで、アイデンティティ > [ロール] を選択します。
-
[ロール] ページで、削除する RAM ロールを見つけ、[操作] 列の ロールの削除 をクリックします。
-
ロールの削除 ダイアログボックスで、確認のため RAM ロール名を入力し、ロールの削除 をクリックします。
説明ポリシーが RAM ロールにアタッチされている場合、ロールを削除すると、ポリシーもデタッチされます。
よくある質問
フロントエンドからの一括アップロード
OSS は一括アップロード API を提供していません。同じ手順を使用して、ループ内でオブジェクトを個別にアップロードしてください。
コールバックリクエストヘッダーのカスタマイズ
いいえ。コールバックボディパラメーターはカスタマイズできますが、リクエストヘッダーはカスタマイズできません。