上传失败,状态代码:403 SignatureDoesNotMatch 当 multiPartUpload 为真时
Upload fails with Status Code: 403 SignatureDoesNotMatch when multiPartUpload is true
我创建了一个简单的骆驼路线来轮询本地目录中的文件,并将它们上传到我大学的 Ceph (S3) 服务器。我将 apache camel 2.20.0 与 camel-aws S3 组件一起使用,当我在 uri 中设置 multiPartUpload=false(默认值)时,一切正常,但如果我更改为 multiPartUpload=true,它将失败。
我知道我的 s3 秘密或 s3 访问密钥没有问题,因为当我设置 multiPartUpload=false 时,一切正常(密钥中没有需要转义的疯狂加号 (+) 字符)。
这是堆栈跟踪:
com.amazonaws.services.s3.model.AmazonS3Exception: null (Service: Amazon S3; Status Code: 403; Error Code: SignatureDoesNotMatch; Request ID: tx000000000000002e9edee-005a4ed3d2-2213a2-uky-campus-1; S3 Extended Request ID: 2213a2-uky-campus-1-uky)
at com.amazonaws.http.AmazonHttpClient$RequestExecutor.handleErrorResponse(AmazonHttpClient.java:1592) ~[aws-java-sdk-core-1.11.186.jar:?]
at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeOneRequest(AmazonHttpClient.java:1257) ~[aws-java-sdk-core-1.11.186.jar:?]
at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeHelper(AmazonHttpClient.java:1029) ~[aws-java-sdk-core-1.11.186.jar:?]
at com.amazonaws.http.AmazonHttpClient$RequestExecutor.doExecute(AmazonHttpClient.java:741) ~[aws-java-sdk-core-1.11.186.jar:?]
at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeWithTimer(AmazonHttpClient.java:715) ~[aws-java-sdk-core-1.11.186.jar:?]
at com.amazonaws.http.AmazonHttpClient$RequestExecutor.execute(AmazonHttpClient.java:697) ~[aws-java-sdk-core-1.11.186.jar:?]
at com.amazonaws.http.AmazonHttpClient$RequestExecutor.access0(AmazonHttpClient.java:665) ~[aws-java-sdk-core-1.11.186.jar:?]
at com.amazonaws.http.AmazonHttpClient$RequestExecutionBuilderImpl.execute(AmazonHttpClient.java:647) ~[aws-java-sdk-core-1.11.186.jar:?]
at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:511) ~[aws-java-sdk-core-1.11.186.jar:?]
at com.amazonaws.services.s3.AmazonS3Client.invoke(AmazonS3Client.java:4227) ~[aws-java-sdk-s3-1.11.186.jar:?]
at com.amazonaws.services.s3.AmazonS3Client.invoke(AmazonS3Client.java:4174) ~[aws-java-sdk-s3-1.11.186.jar:?]
at com.amazonaws.services.s3.AmazonS3Client.abortMultipartUpload(AmazonS3Client.java:2928) ~[aws-java-sdk-s3-1.11.186.jar:?]
at org.apache.camel.component.aws.s3.S3Producer.processMultiPart(S3Producer.java:181) ~[camel-aws-2.20.0.jar:2.20.0]
at org.apache.camel.component.aws.s3.S3Producer.process(S3Producer.java:84) ~[camel-aws-2.20.0.jar:2.20.0]
at ...
我的 camel-context.xml 看起来像:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
<bean id="properties"
class="org.apache.camel.component.properties.PropertiesComponent">
<property name="location" value="config.properties" />
</bean>
<bean id="bridgePropertyPlaceholder"
class="org.apache.camel.spring.spi.BridgePropertyPlaceholderConfigurer">
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
<property name="location" value="config.properties" />
</bean>
<bean id="amazonClient" class="com.amazonaws.services.s3.AmazonS3Client">
<constructor-arg>
<bean class="com.amazonaws.auth.BasicAWSCredentials">
<constructor-arg name="accessKey" value="${s3AccessKey}" />
<constructor-arg name="secretKey" value="${s3SecretKey}" />
</bean>
</constructor-arg>
<property name="s3ClientOptions">
<bean class="com.amazonaws.services.s3.S3ClientOptions">
<property name="pathStyleAccess" value="true" />
</bean>
</property>
<property name="endpoint" value="${s3Endpoint}" />
</bean>
<camelContext xmlns="http://camel.apache.org/schema/spring">
<route>
<from uri="file:target/sendToS3/?antInclude=*.*" />
<log message="Found file: ${in.header.CamelFileName}" />
<setHeader headerName="CamelAwsS3Key">
<simple>testMultiPart/${in.header.CamelFileName}
</simple>
</setHeader>
<setHeader headerName="CamelAwsS3ContentLength">
<simple>${in.header.CamelFileLength}
</simple>
</setHeader>
<log message="Send file to S3: ${properties:s3Endpoint}" />
<to uri="aws-s3://{{s3Bucket}}?amazonS3Client=#amazonClient&multiPartUpload=true" />
<log message="Done sending file." />
</route>
</camelContext>
</beans>
我尝试了很多方法,例如:
- 将 CamelAwsS3ContentMD5 header 设置为文件的 MD5 哈希(这对 multi-part 文件没有意义)
- partSize 参数的各种设置
- 不同大小的文件,从非常大到非常小
- 设置系统参数:System.setProperty("com.amazonaws.services.s3.disablePutObjectMD5Validation","true");
如果我打开 camel 的跟踪调试,也没什么用:
[d #2 - file://target/sendToS3/] S3Producer TRACE Initiating multipart upload [com.amazonaws.services.s3.model.InitiateMultipartUploadRequest@3731147a] from exchange [Exchange[ID-Toucan-local-1515115111374-0-1]]...
[d #2 - file://target/sendToS3/] S3Producer TRACE Uploading part [1] for testMultiPart/testfile.zip
[d #2 - file://target/sendToS3/] DefaultErrorHandler TRACE Is exchangeId: ID-Toucan-local-1515115111374-0-1 interrupted? false
[d #2 - file://target/sendToS3/] DefaultErrorHandler TRACE Is exchangeId: ID-Toucan-local-1515115111374-0-1 done? false
[d #2 - file://target/sendToS3/] DefaultErrorHandler TRACE isRunAllowed() -> true (Run allowed if we are not stopped/stopping)
[d #2 - file://target/sendToS3/] DefaultExceptionPolicyStrategy TRACE Finding best suited exception policy for thrown exception com.amazonaws.services.s3.model.AmazonS3Exception
[d #2 - file://target/sendToS3/] DefaultExceptionPolicyStrategy TRACE Finding best suited exception policy for thrown exception com.amazonaws.services.s3.model.AmazonS3Exception
[d #2 - file://target/sendToS3/] DefaultExceptionPolicyStrategy TRACE Found 0 candidates
[d #2 - file://target/sendToS3/] DefaultErrorHandler DEBUG Failed delivery for (MessageId: ID-Toucan-local-1515115111374-0-2 on ExchangeId: ID-Toucan-local-1515115111374-0-1). On delivery attempt: 0 caught: com.amazonaws.services.s3.model.AmazonS3Exception: null (Service: Amazon S3; Status Code: 403; Error Code: SignatureDoesNotMatch; Request ID: tx000000000000002e9edee-005a4ed3d2-2213a2-uky-campus-1; S3 Extended Request ID: 2213a2-uky-campus-1-uky), S3 Extended Request ID: 2213a2-uky-campus-1-uky
[d #2 - file://target/sendToS3/] DefaultErrorHandler TRACE isRedeliveryAllowed() -> true (we are not stopping/stopped)
[d #2 - file://target/sendToS3/] DefaultErrorHandler TRACE This exchange is not handled or continued so its marked as failed: Exchange[ID-Toucan-local-1515115111374-0-1]
[d #2 - file://target/sendToS3/] InstrumentationProcessor TRACE to: Recording duration: 356930 millis for exchange: Exchange[ID-Toucan-local-1515115111374-0-1]
[d #2 - file://target/sendToS3/] DefaultErrorHandler ERROR Failed delivery for (MessageId: ID-Toucan-local-1515115111374-0-2 on ExchangeId: ID-Toucan-local-1515115111374-0-1). Exhausted after delivery attempt: 1 caught: com.amazonaws.services.s3.model.AmazonS3Exception: null (Service: Amazon S3; Status Code: 403; Error Code: SignatureDoesNotMatch; Request ID: tx000000000000002e9edee-005a4ed3d2-2213a2-uky-campus-1; S3 Extended Request ID: 2213a2-uky-campus-1-uky), S3 Extended Request ID: 2213a2-uky-campus-1-uky
我需要 multi-part 上传的原因是为了处理非常大的文件,但我无法让它处理任何文件大小。
原来...
由于端点是 Ceph 服务器,分段上传将不起作用,除非您在 S3 ClientConfiguration 中将 signerOverride 设置为 'S3SignerType',如下所示:
<bean id="amazonClient" class="com.amazonaws.services.s3.AmazonS3Client">
<constructor-arg>
<bean class="com.amazonaws.auth.BasicAWSCredentials">
<constructor-arg name="accessKey" value="${s3AccessKey}" />
<constructor-arg name="secretKey" value="${s3SecretKey}" />
</bean>
</constructor-arg>
<!-- *** The following option must be set in order for multipart uploads to work on a Ceph server *** -->
<constructor-arg>
<bean class="com.amazonaws.ClientConfiguration">
<property name="signerOverride" value="S3SignerType" />
</bean>
</constructor-arg>
<property name="s3ClientOptions">
<bean class="com.amazonaws.services.s3.S3ClientOptions">
<property name="pathStyleAccess" value="true" />
</bean>
</property>
<property name="endpoint" value="${s3Endpoint}" />
</bean>
也许这个要求会在 Ceph 的更高版本中消失,我连接的版本早于 v12 (Luminous),但我不确定确切的版本。或者,这可能是服务于 Ceph 集群的 HTTPS 前端的限制 - 我不确定。
我创建了一个简单的骆驼路线来轮询本地目录中的文件,并将它们上传到我大学的 Ceph (S3) 服务器。我将 apache camel 2.20.0 与 camel-aws S3 组件一起使用,当我在 uri 中设置 multiPartUpload=false(默认值)时,一切正常,但如果我更改为 multiPartUpload=true,它将失败。
我知道我的 s3 秘密或 s3 访问密钥没有问题,因为当我设置 multiPartUpload=false 时,一切正常(密钥中没有需要转义的疯狂加号 (+) 字符)。
这是堆栈跟踪:
com.amazonaws.services.s3.model.AmazonS3Exception: null (Service: Amazon S3; Status Code: 403; Error Code: SignatureDoesNotMatch; Request ID: tx000000000000002e9edee-005a4ed3d2-2213a2-uky-campus-1; S3 Extended Request ID: 2213a2-uky-campus-1-uky)
at com.amazonaws.http.AmazonHttpClient$RequestExecutor.handleErrorResponse(AmazonHttpClient.java:1592) ~[aws-java-sdk-core-1.11.186.jar:?]
at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeOneRequest(AmazonHttpClient.java:1257) ~[aws-java-sdk-core-1.11.186.jar:?]
at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeHelper(AmazonHttpClient.java:1029) ~[aws-java-sdk-core-1.11.186.jar:?]
at com.amazonaws.http.AmazonHttpClient$RequestExecutor.doExecute(AmazonHttpClient.java:741) ~[aws-java-sdk-core-1.11.186.jar:?]
at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeWithTimer(AmazonHttpClient.java:715) ~[aws-java-sdk-core-1.11.186.jar:?]
at com.amazonaws.http.AmazonHttpClient$RequestExecutor.execute(AmazonHttpClient.java:697) ~[aws-java-sdk-core-1.11.186.jar:?]
at com.amazonaws.http.AmazonHttpClient$RequestExecutor.access0(AmazonHttpClient.java:665) ~[aws-java-sdk-core-1.11.186.jar:?]
at com.amazonaws.http.AmazonHttpClient$RequestExecutionBuilderImpl.execute(AmazonHttpClient.java:647) ~[aws-java-sdk-core-1.11.186.jar:?]
at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:511) ~[aws-java-sdk-core-1.11.186.jar:?]
at com.amazonaws.services.s3.AmazonS3Client.invoke(AmazonS3Client.java:4227) ~[aws-java-sdk-s3-1.11.186.jar:?]
at com.amazonaws.services.s3.AmazonS3Client.invoke(AmazonS3Client.java:4174) ~[aws-java-sdk-s3-1.11.186.jar:?]
at com.amazonaws.services.s3.AmazonS3Client.abortMultipartUpload(AmazonS3Client.java:2928) ~[aws-java-sdk-s3-1.11.186.jar:?]
at org.apache.camel.component.aws.s3.S3Producer.processMultiPart(S3Producer.java:181) ~[camel-aws-2.20.0.jar:2.20.0]
at org.apache.camel.component.aws.s3.S3Producer.process(S3Producer.java:84) ~[camel-aws-2.20.0.jar:2.20.0]
at ...
我的 camel-context.xml 看起来像:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
<bean id="properties"
class="org.apache.camel.component.properties.PropertiesComponent">
<property name="location" value="config.properties" />
</bean>
<bean id="bridgePropertyPlaceholder"
class="org.apache.camel.spring.spi.BridgePropertyPlaceholderConfigurer">
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
<property name="location" value="config.properties" />
</bean>
<bean id="amazonClient" class="com.amazonaws.services.s3.AmazonS3Client">
<constructor-arg>
<bean class="com.amazonaws.auth.BasicAWSCredentials">
<constructor-arg name="accessKey" value="${s3AccessKey}" />
<constructor-arg name="secretKey" value="${s3SecretKey}" />
</bean>
</constructor-arg>
<property name="s3ClientOptions">
<bean class="com.amazonaws.services.s3.S3ClientOptions">
<property name="pathStyleAccess" value="true" />
</bean>
</property>
<property name="endpoint" value="${s3Endpoint}" />
</bean>
<camelContext xmlns="http://camel.apache.org/schema/spring">
<route>
<from uri="file:target/sendToS3/?antInclude=*.*" />
<log message="Found file: ${in.header.CamelFileName}" />
<setHeader headerName="CamelAwsS3Key">
<simple>testMultiPart/${in.header.CamelFileName}
</simple>
</setHeader>
<setHeader headerName="CamelAwsS3ContentLength">
<simple>${in.header.CamelFileLength}
</simple>
</setHeader>
<log message="Send file to S3: ${properties:s3Endpoint}" />
<to uri="aws-s3://{{s3Bucket}}?amazonS3Client=#amazonClient&multiPartUpload=true" />
<log message="Done sending file." />
</route>
</camelContext>
</beans>
我尝试了很多方法,例如:
- 将 CamelAwsS3ContentMD5 header 设置为文件的 MD5 哈希(这对 multi-part 文件没有意义)
- partSize 参数的各种设置
- 不同大小的文件,从非常大到非常小
- 设置系统参数:System.setProperty("com.amazonaws.services.s3.disablePutObjectMD5Validation","true");
如果我打开 camel 的跟踪调试,也没什么用:
[d #2 - file://target/sendToS3/] S3Producer TRACE Initiating multipart upload [com.amazonaws.services.s3.model.InitiateMultipartUploadRequest@3731147a] from exchange [Exchange[ID-Toucan-local-1515115111374-0-1]]...
[d #2 - file://target/sendToS3/] S3Producer TRACE Uploading part [1] for testMultiPart/testfile.zip
[d #2 - file://target/sendToS3/] DefaultErrorHandler TRACE Is exchangeId: ID-Toucan-local-1515115111374-0-1 interrupted? false
[d #2 - file://target/sendToS3/] DefaultErrorHandler TRACE Is exchangeId: ID-Toucan-local-1515115111374-0-1 done? false
[d #2 - file://target/sendToS3/] DefaultErrorHandler TRACE isRunAllowed() -> true (Run allowed if we are not stopped/stopping)
[d #2 - file://target/sendToS3/] DefaultExceptionPolicyStrategy TRACE Finding best suited exception policy for thrown exception com.amazonaws.services.s3.model.AmazonS3Exception
[d #2 - file://target/sendToS3/] DefaultExceptionPolicyStrategy TRACE Finding best suited exception policy for thrown exception com.amazonaws.services.s3.model.AmazonS3Exception
[d #2 - file://target/sendToS3/] DefaultExceptionPolicyStrategy TRACE Found 0 candidates
[d #2 - file://target/sendToS3/] DefaultErrorHandler DEBUG Failed delivery for (MessageId: ID-Toucan-local-1515115111374-0-2 on ExchangeId: ID-Toucan-local-1515115111374-0-1). On delivery attempt: 0 caught: com.amazonaws.services.s3.model.AmazonS3Exception: null (Service: Amazon S3; Status Code: 403; Error Code: SignatureDoesNotMatch; Request ID: tx000000000000002e9edee-005a4ed3d2-2213a2-uky-campus-1; S3 Extended Request ID: 2213a2-uky-campus-1-uky), S3 Extended Request ID: 2213a2-uky-campus-1-uky
[d #2 - file://target/sendToS3/] DefaultErrorHandler TRACE isRedeliveryAllowed() -> true (we are not stopping/stopped)
[d #2 - file://target/sendToS3/] DefaultErrorHandler TRACE This exchange is not handled or continued so its marked as failed: Exchange[ID-Toucan-local-1515115111374-0-1]
[d #2 - file://target/sendToS3/] InstrumentationProcessor TRACE to: Recording duration: 356930 millis for exchange: Exchange[ID-Toucan-local-1515115111374-0-1]
[d #2 - file://target/sendToS3/] DefaultErrorHandler ERROR Failed delivery for (MessageId: ID-Toucan-local-1515115111374-0-2 on ExchangeId: ID-Toucan-local-1515115111374-0-1). Exhausted after delivery attempt: 1 caught: com.amazonaws.services.s3.model.AmazonS3Exception: null (Service: Amazon S3; Status Code: 403; Error Code: SignatureDoesNotMatch; Request ID: tx000000000000002e9edee-005a4ed3d2-2213a2-uky-campus-1; S3 Extended Request ID: 2213a2-uky-campus-1-uky), S3 Extended Request ID: 2213a2-uky-campus-1-uky
我需要 multi-part 上传的原因是为了处理非常大的文件,但我无法让它处理任何文件大小。
原来...
由于端点是 Ceph 服务器,分段上传将不起作用,除非您在 S3 ClientConfiguration 中将 signerOverride 设置为 'S3SignerType',如下所示:
<bean id="amazonClient" class="com.amazonaws.services.s3.AmazonS3Client">
<constructor-arg>
<bean class="com.amazonaws.auth.BasicAWSCredentials">
<constructor-arg name="accessKey" value="${s3AccessKey}" />
<constructor-arg name="secretKey" value="${s3SecretKey}" />
</bean>
</constructor-arg>
<!-- *** The following option must be set in order for multipart uploads to work on a Ceph server *** -->
<constructor-arg>
<bean class="com.amazonaws.ClientConfiguration">
<property name="signerOverride" value="S3SignerType" />
</bean>
</constructor-arg>
<property name="s3ClientOptions">
<bean class="com.amazonaws.services.s3.S3ClientOptions">
<property name="pathStyleAccess" value="true" />
</bean>
</property>
<property name="endpoint" value="${s3Endpoint}" />
</bean>
也许这个要求会在 Ceph 的更高版本中消失,我连接的版本早于 v12 (Luminous),但我不确定确切的版本。或者,这可能是服务于 Ceph 集群的 HTTPS 前端的限制 - 我不确定。