Web フォームから直接 Amazon S3 に非同期でファイルをアップロードしようとしています。これを行うには、サーバーにファイルをアップロードするクライアント リクエストを認証する必要があります。
AWS シークレット キーを使用してアップロード リクエストにデジタル署名することで、クライアントがファイルを S3 バケットにアップロードするために使用できる一時的な認証済み URL を作成できます。
Amazon S3 ドキュメントでは、署名は次の方法で生成する必要があると指定されています。
Signature = URL-Encode( Base64( HMAC-SHA1( YourSecretAccessKeyID,
UTF-8-Encoding-Of( StringToSign ) ) ) );
サーバーでHaskellを使用しているため、実装は次のようになります。
{-# LANGUAGE OverloadedStrings #-}
import qualified Data.ByteString.Base64.Lazy as B64
import qualified Data.Digest.Pure.SHA as SHA
import qualified Data.ByteString.Lazy.Char8 as BL8
sign :: BL8.ByteString -> BL8.ByteString
sign = B64.encode . SHA.bytestringDigest . SHA.hmacSha1 secret
where secret = "aws-secret-key"
Amazon ドキュメントの形式では、StringToSign が次のようになっている必要があります。
StringToSign = HTTP-VERB + "\n" +
Content-MD5 + "\n" +
Content-Type + "\n" +
Expires + "\n" +
CanonicalizedAmzHeaders +
CanonicalizedResource;
Amazon からの別の例:
GET\n
\n
\n
1175139620\n
/johnsmith/photos/puppy.jpg
したがって、私の文字列は次のようになります。
"PUT\n\n\n1384330538\n/バケット名/オブジェクト名"
上記の文字列に (sign 関数を使用して) 署名し、次のような URL を作成します。
https://s3.amazonaws.com/bucketname/objname?AWSAccessKeyId=accessskey&Signature=signature=&Expires=1384330979
これは、アップロードの前に AJAX リクエストを介してクライアントに送信されます。PUT リクエストを許可するために、バケットの CORS ポリシーも更新しました。
問題は、上記の署名付き URL で何かをアップロードしようとするたびに、このメッセージが (XML ドキュメントで) 表示されることです。
計算したリクエストの署名が、提供された署名と一致しません。キーと署名方法を確認してください。
だから私はどこで間違ったのか分かりません。注: パブリック URL ( https://s3.amazonaws.com/bucketname/objname )を使用すればアップロードできます(ただし、これはすべきではありません。ユーザーに BLOB のアップロードのみを許可し、読み取りや削除などは許可しないでください)。