S3にファイルをアップロードする必要があるPlayアプリケーションがあります。 scalaで開発し、Java AWS SDKを使用しています。
ファイルをアップロードしようとして問題が発生しました。署名付きURLを使用すると、403 SignatureDoesNotMatchが表示され続けます。 URLはAWS Java SDKを使用して次のコードで生成されています:
def generatePresignedPutRequest(filename: String) = {
val expiration = new Java.util.Date();
var msec = expiration.getTime() + 1000 * 60 * 60; // Add 1 hour.
expiration.setTime(msec);
s3 match {
case Some(s3) => s3.generatePresignedUrl(bucketname, filename, expiration, HttpMethod.PUT).toString
case None => {
Logger.warn("S3 is not availiable. Cannot generate PUT request.")
"URL not availiable"
}
}
}
フロントエンドコードは ioncannon article に従いました。
ファイルをアップロードするjs関数(記事で使用したものと同じ)
function uploadToS3(file, url)
{
var xhr = createCORSRequest('PUT', url);
if (!xhr)
{
setProgress(0, 'CORS not supported');
}
else
{
xhr.onload = function()
{
if(xhr.status == 200)
{
setProgress(100, 'Upload completed.');
}
else
{
setProgress(0, 'Upload error: ' + xhr.status);
}
};
xhr.onerror = function()
{
setProgress(0, 'XHR error.');
};
xhr.upload.onprogress = function(e)
{
if (e.lengthComputable)
{
var percentLoaded = Math.round((e.loaded / e.total) * 100);
setProgress(percentLoaded, percentLoaded == 100 ? 'Finalizing.' : 'Uploading.');
}
};
xhr.setRequestHeader('Content-Type', 'image/png');
xhr.setRequestHeader('x-amz-acl', 'authenticated-read');
xhr.send(file);
}
}
サーバーの応答は
<?xml version="1.0" encoding="UTF-8"?>
<Error><Code>SignatureDoesNotMatch</Code>
<Message>The request signature we calculated does not match the signature you provided. Check your key and signing method.</Message>
<StringToSignBytes>50 55 bla bla bla...</StringToSignBytes>
<RequestId>F7A8F1659DE5909C</RequestId>
<HostId>q+r+2T5K6mWHLKTZw0R9/jm22LyIfZFBTY8GEDznfmJwRxvaVJwPiu/hzUfuJWbW</HostId>
<StringToSign>PUT
image/png
1387565829
x-amz-acl:authenticated-read
/mybucketname/icons/f5430c16-32da-4315-837f-39a6cf9f47a1</StringToSign>
<AWSAccessKeyId>myaccesskey</AWSAccessKeyId></Error>
CORSを構成し、aws資格情報を再確認し、リクエストヘッダーを変更してみました。私はいつも同じ結果を得ます。なぜAmazonは署名が一致しないと私に言っているのですか?
OPにはまだこの問題がありますが、これに遭遇した他の誰にとっても、ここに答えがあります:
AWSは、S3への署名付きリクエストを行うときに、ブラウザーが送信したHTTPヘッダー情報と署名が正確に一致することを確認します。残念ながらこれは必要な資料です: http://s3.amazonaws.com/doc/s3-developer-guide/RESTAuthentication.html
ただし、上記のコードでは実際にはそうではなく、JavaScriptが送信しています。
xhr.setRequestHeader('Content-Type', 'image/png');
xhr.setRequestHeader('x-amz-acl', 'authenticated-read');
しかし、Java/Scalaでは、どちらも渡さずにs3.generatePresignedUrlが呼び出されています。したがって、結果の署名は、実際にはS3にContent-Typeまたはx-ams-aclヘッダーセットを持つものをすべて拒否するように指示しています。 Oops(私も落ちました)。
ブラウザがContent-Typesを自動的に送信するのを見たので、明示的にヘッダーに追加されていなくても、S3に入る可能性があります。問題は、Content-Typeヘッダーとx-amz-aclヘッダーを署名にどのように追加するかということです。
AWS SDKには、オーバーロードされたgeneratePresignedUrl関数がいくつかありますが、バケット名、ファイル名、有効期限、およびhttpメソッド以外に渡すことができるのはそのうちの1つだけです。
解決策は次のとおりです。
以下は、使用するGeneratePresignedUrlRequestの適切な関数定義です。
AWS GitHubリポジトリにある関数のコードも、ソリューションのコーディング方法を確認するのに役立ちました。お役に立てれば。
NodeJs AWS SDKを使用してこの問題が発生しました。有効な資格情報を使用したことが原因でしたただし、十分な権限がありません。管理者キーに変更すると、コードを変更せずにこれを修正しました!
私は同様の問題に直面し、設定を設定しましたsignatureVersion: 'v4'
私の場合、それを解決するのに役立ちました-
JavaScriptの場合:
var s3 = new AWS.S3({
signatureVersion: 'v4'
});
https://github.com/aws/aws-sdk-js/issues/902#issuecomment-184872976 から変更
同じ問題がありましたが、content-typeを削除しても問題ありません。これにより、完全なコードが共有されます。
public class GeneratePresignedUrlAndUploadObject {
private static final String BUCKET_NAME = "<YOUR_AWS_BUCKET_NAME>";
private static final String OBJECT_KEY = "<YOUR_AWS_KEY>";
private static final String AWS_ACCESS_KEY = "<YOUR_AWS_ACCESS_KEY>";
private static final String AWS_SECRET_KEY = "<YOUR_AWS_SECRET_KEY>";
public static void main(String[] args) throws IOException {
BasicAWSCredentials awsCreds = new BasicAWSCredentials(AWS_ACCESS_KEY, AWS_SECRET_KEY);
AmazonS3 s3Client = AmazonS3ClientBuilder.standard().withRegion(Regions.US_EAST_1)
.withCredentials(new AWSStaticCredentialsProvider(awsCreds)).build();
try {
System.out.println("Generating pre-signed URL.");
Java.util.Date expiration = new Java.util.Date();
long milliSeconds = expiration.getTime();
milliSeconds += 1000 * 60 * 60;
expiration.setTime(milliSeconds);
GeneratePresignedUrlRequest generatePresignedUrlRequest =
new GeneratePresignedUrlRequest(BUCKET_NAME, OBJECT_KEY);
generatePresignedUrlRequest.setMethod(HttpMethod.PUT);
generatePresignedUrlRequest.setExpiration(expiration);
URL url = s3Client.generatePresignedUrl(generatePresignedUrlRequest);
UploadObject(url);
System.out.println("Pre-Signed URL = " + url.toString());
} catch (AmazonServiceException exception) {
System.out.println("Caught an AmazonServiceException, " +
"which means your request made it " +
"to Amazon S3, but was rejected with an error response " +
"for some reason.");
System.out.println("Error Message: " + exception.getMessage());
System.out.println("HTTP Code: " + exception.getStatusCode());
System.out.println("AWS Error Code:" + exception.getErrorCode());
System.out.println("Error Type: " + exception.getErrorType());
System.out.println("Request ID: " + exception.getRequestId());
} catch (AmazonClientException ace) {
System.out.println("Caught an AmazonClientException, " +
"which means the client encountered " +
"an internal error while trying to communicate" +
" with S3, " +
"such as not being able to access the network.");
System.out.println("Error Message: " + ace.getMessage());
}
}
public static void UploadObject(URL url) throws IOException
{
HttpURLConnection connection=(HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setRequestMethod("PUT");
OutputStreamWriter out = new OutputStreamWriter(
connection.getOutputStream());
out.write("This text uploaded as object.");
out.close();
int responseCode = connection.getResponseCode();
System.out.println("Service returned response code " + responseCode);
}
}
私にとっては同じ問題ですが、原因は異なります。 PUTの代わりにPOSTを使用していた
問題が発生しました。WindowsのMIMEタイプでfileTypeが空の文字列に設定されていて、機能しませんでした。空の文字列を処理し、ファイルタイプを追加するだけです。
Java AWS SDK
を使用してSignatureDoesNotMatch
エラーに直面しました。私の場合、コードを変更せずにMavenの依存関係をアップグレードした後にSignatureDoesNotMatch
エラーが発生しました(資格情報は正しく、変更されていません)。依存関係org.Apache.httpcomponents:httpclient
をバージョン4.5.6
から4.5.7
にアップグレードした後(実際にはSpring Boot
の2.1.2
から2.1.3
へのアップグレードであり、そこにbom
はhttpclient
versionを指定しています)、AmazonS3.getObject
のようないくつかのAWS SDK S3リクエストの実行中にコードが例外をスローするようになりました。
根本的な原因を掘り下げた後、httpclient
ライブラリが正規化されたURIで重大な変更を行い、Java AWS SDK S3に影響を及ぼしました。開いているGitHubチケットを確認してください- org.Apache.httpcomponents:httpclient:4.5.7はS3オブジェクトのフェッチを中断します 詳細。