私はAmazon S3の署名済みURLで一晩中ファイルをPUTしようとしていました。署名済みURLをJavaコードで生成します。
AWSCredentials credentials = new BasicAWSCredentials( accessKey, secretKey );
client = new AmazonS3Client( credentials );
GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest( bucketName, "myfilename", HttpMethod.PUT);
request.setExpiration( new Date( System.currentTimeMillis() + (120 * 60 * 1000) ));
return client.generatePresignedUrl( request ).toString();
次に、生成された署名済みURLを使用して、curlを使用してファイルをPUTします。
curl -v -H "content-type:image/jpg" -T mypicture.jpg https://mybucket.s3.amazonaws.com/myfilename?Expires=1334126943&AWSAccessKeyId=<accessKey>&Signature=<generatedSignature>
GETのように、これはパブリックではないバケットで機能すると想定していました(それが署名済みのポイントですよね?)さて、すべての試行でアクセスが拒否されました。最後にフラストレーションから私はバケットのアクセス許可を変更して、全員が書き込みできるようにしました。もちろん、署名済みURLは機能しました。私はすぐにEVERYONE権限をバケットから削除しました。現在、自分の自己署名付きURLによってバケットにアップロードされたアイテムを削除する権限がありません。私は今見る私はおそらく私がアップロードものにX-AMZ-aclのヘッダーを入れている必要があること。これを正しく行う前に、削除できないオブジェクトをさらにいくつか作成するのではないかと思います。
これはいくつかの質問につながります:
最終目標は、携帯電話がこの署名済みURLを使用して画像をPUTすることです。私はそれを概念実証としてカールで動かそうとしている。
アップデート:私は質問尋ねアマゾンフォーラムを。そこに回答が提供されている場合は、ここに回答として記載します。
これは確かに少し不可解ですが、私はそれをAWS SDK for Javaのバグだと考えています(以下を参照)-ただし、何よりもまず、次のcurlコマンドがファイルをアップロードします(もちろん、更新済みの署名済みURLを想定しています) ):
curl -v -T mypicture.jpg https://mybucket.s3.amazonaws.com/myfilename?Expires=1334126943&AWSAccessKeyId=<accessKey>&Signature=<generatedSignature>
つまり、結果として(または)Content type
を生成するヘッダーを除外しましたが、これは明らかに望ましくありません。したがって、さらなる掘り起こしが必要でした。application/octet-stream
binary/octet-stream
Amazon S3へのPUT(およびDELETEとHEAD)リクエストの事前署名付きURLは、原則として機能することがわかっており、このサイトの関連する質問で最も明白ではありません(たとえば、事前署名付きのs3へのアップロードとカールへの私の回答を参照)URL(403を取得))。
簡易化されたクエリ文字列要求認証の代替は、クエリ文字列要求認証方法を示す次の疑似文法を使用するように文書化されています。
StringToSign = HTTP-VERB + "\n" +
Content-MD5 + "\n" +
Content-Type + "\n" +
Expires + "\n" +
CanonicalizedAmzHeaders +
CanonicalizedResource;
これにはContent-Type
ヘッダーが含まれますが、(すでに発見したように)いくつかの文書化されたケースではこれが欠けている部分です。たとえば、PUTリクエストを使用したGetPreSignedURLに対するAWSチームの応答を参照してください。追加すると、有効な署名済みURLが生成されます。
これは、AWS SDK for .NETを使用して簡単に実現できます。これは、まさにそれを行うための便利なメソッドGetPreSignedUrlRequest.WithContentTypeを提供します。
このリクエストのContentTypeプロパティを設定します。このプロパティのデフォルトは「binary / octet-stream」ですが、必要な場合はこのプロパティを設定できます。
したがって、次のように、それぞれのサンプル「署名済みURLを使用したオブジェクトのアップロード-AWS SDK for .NET」を拡張すると、コンテンツタイプが含まれた有効な署名済みURLが生成されます。これは、curlを介して(つまり、意図したとおりに)アップロードできます。
// ...
GetPreSignedUrlRequest request = new GetPreSignedUrlRequest();
// ...
request.WithContentType("image/jpg");
// ...
次に、意味的に同一のサンプルを拡張し、事前署名済みURLを使用してオブジェクトをアップロードする-AWS SDK for Javaを同様の方法で拡張しますが、(すでに発見したように)これを実現する専用の方法はありません。これは便利なメソッドが欠けているだけかもしれませんが、最終的にはaddRequestParameter()またはsetResponseHeaders()を使用して実現できる可能性があります。例:
// ...
request.setExpiration( new Date( System.currentTimeMillis() + (120 * 60 * 1000) ));
request.addRequestParameter("content-type", "image/jpg");
return client.generatePresignedUrl( request ).toString();
// ...
ただし、両方のメソッドのドキュメントは他の目的を示唆しており、実際には機能しません。つまり、どのコンテンツタイプがそのように設定されていても(もしあれば)常に同じ署名を生成します。
SDKをさらにデバッグすると、どちらも前述の疑似文法に従ってクエリ文字列認証を計算するための意味論的に類似したコアメソッドを提供していることがわかります。.NETのbuildSigningString()およびJavaのmakeS3CanonicalString()を参照してください。
しかし、すべての興味深いヘッダーをリストに追加し、それらをソートする Javaバージョンのそれぞれのコードは、「興味深い」がContent-MD5、Content-Type、Date、およびx-amz-として定義されているため、実際には決して実行されません。いかなるクラスにのみ利用可能である何とかこれらのヘッダを提供する方法であって、実際に存在しないDefaultRequestクラスないGeneratePresignedUrlRequestが保護方法を参照、順番に署名を計算するための入力として使用され、前者を初期化するために使用createRequestは() 。
Javaは、ほぼ逆の組み合わせから自分の入力を構成する対興味深いことに/注目すべきは、二つの方法は、.NETでのクエリ文字列認証を計算するために、ヘッダ対パラメータのJavaのバグの原因にヒントができコールスタック、上のソースが、もちろん、それを解読するのは難しいかもしれません。つまり、内部アーキテクチャはもちろん大きく異なる可能性があります。
これには2つの角度があります。
結論として、これを解決するための唯一の合理的な方法は更新されたSDKであるため、バグレポートが必要です。明らかに、このSDKの機能を複製または拡張して、この特別なケースを個別に説明できます(理想的には、送信できるようにする方法で)aws-sdk-for-javaプロジェクトのプルリクエスト)ですが、互換性と保守性のある方法でこれを正しく行うことは少し難しいように思われるため、SDKメンテナー自身が行うのが最善です。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加