import java.io.File;
 
import com.amazonaws.AmazonClientException;

import com.amazonaws.auth.profile.ProfileCredentialsProvider;

import com.amazonaws.services.s3.transfer.TransferManager;

import com.amazonaws.services.s3.transfer.Upload;

 

public class UploadObjectMultipartUploadUsingHighLevelAPI {

 
    public static void main(String[] args) throws Exception {

        String existingBucketName = "*** Provide existing bucket name ***";

        String keyName            = "*** Provide object key ***";

        String filePath           = "*** Path to and name of the file to upload ***"

         

        TransferManager tm = new TransferManager(new ProfileCredentialsProvider());       

        System.out.println("Hello");

        // TransferManager processes all transfers asynchronously,

        // so this call will return immediately.

        Upload upload = tm.upload(

                existingBucketName, keyName, new File(filePath));

        System.out.println("Hello2");

 

        try {

            // Or you can block and wait for the upload to finish

            upload.waitForCompletion();

            System.out.println("Upload complete.");

        catch (AmazonClientException amazonClientException) {

            System.out.println("Unable to upload file, upload was aborted.");

            amazonClientException.printStackTrace();

        }

    }

}
 

问题描述:使用s3 java sdk 的如上代码分片文件上传,报‘SignatureDoesNotMatch’ 异常如下

Unable to abort multipart upload, you may need to manually remove uploaded parts: null (Service: Amazon S3; Status Code: 403; Error Code: SignatureDoesNotMatch; Request ID: tx000000000000000003ddf-005853b76e-1a56f9b-default)
com.amazonaws.services.s3.model.AmazonS3Exception: null (Service: Amazon S3; Status Code: 403; Error Code: SignatureDoesNotMatch; Request ID: tx000000000000000003ddf-005853b76e-1a56f9b-default), S3 Extended Request ID: 1a56f9b-default-default

定位过程:

下载s3 java sdk 源码,并配置好 log4j, 打印aws debug日志;

# For JBoss: Avoid to setup Log4J outside $JBOSS_HOME/server/default/deploy/log4j.xml!
# For all other servers: Comment out the Log4J listener in web.xml to activate Log4J.
#log4j.rootLogger=INFO, stdout, logfile
log4j.rootLogger=INFO,stdout,logfile
log4j.logger.com.amazonaws = DEBUG
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - <%m>%n

RGW配置文件/etc/ceph/ceph.conf 中的日志级别调整为20,重启RGW进程

debug rgw = 20

执行分片上传代码,分别截获客户端和服务端的请求日志。 如下2个图片可以发现uploadId客户端和服务端不一致,导致服务端进行签名校验失败。

那么问题来了,到底是RGW服务端,还是java s3 sdk实现有bug呢? 通过查看java 代码和aws文档描述,我认为是RGW签名实现存在bug。 RGW 应该在

获取从客户端url中的参数中值(已经被URLEncode)后,先decode,再根据aws文档描述的步骤进行encode(~特殊字符不encode),得到符合规则的参数字符串。

.\src\rgw\rgw_rest_s3.cc

http://docs.aws.amazon.com/general/latest/gr/sigv4-create-canonical-request.html

规避方案:

因为修改RGW的代码周期比较长,暂时先修改好修改的java代码,编译一个新的jar包。 如下是修改方法,不按照aws的规则来,对参数值只执行URLencode。

提交了一个bugfix到rgw git库, https://github.com/ceph/ceph/pull/12647/commits

https://github.com/BodihTao/aws-sdk-java/blob/master/aws-java-sdk-core/src/main/java/com/amazonaws/auth/AbstractAWSSigner.java

为了方便大家,我上传修改后编译好的class文件(java 1.8版本),把这2个文件用winrar 放到aws-java-sdk-1.11.69.jar包中com/amazonaws/auth目录下 替换原来文件即可得到新的jar包。

https://github.com/BodihTao/aws-sdk-java/raw/master/aws-java-sdk/AbstractAWSSigner%241.class

https://github.com/BodihTao/aws-sdk-java/raw/master/aws-java-sdk/AbstractAWSSigner.class

java 1.7版本的sdk包:

http://s3.yyclouds.com/public/aws-java-sdk-1.11.69rgw.jar

Ceph RGW服务 使用s3 java sdk 分片文件上传API 报‘SignatureDoesNotMatch’ 异常的定位及规避方案的更多相关文章

  1. Java FtpClient 实现文件上传服务

    一.Ubuntu 安装 Vsftpd 服务 1.安装 sudo apt-get install vsftpd 2.添加用户(uftp) sudo useradd -d /home/uftp -s /b ...

  2. Java开发系列-文件上传

    概述 Java开发中文件上传的方式有很多,常见的有servlet3.0.common-fileUpload.框架.不管哪种方式,对于文件上传的本质是不变的. 文件上传的准备 文件上传需要客户端跟服务都 ...

  3. Java中实现文件上传下载的三种解决方案

    第一点:Java代码实现文件上传 FormFile file=manform.getFile(); String newfileName = null; String newpathname=null ...

  4. 【原创】用JAVA实现大文件上传及显示进度信息

    用JAVA实现大文件上传及显示进度信息 ---解析HTTP MultiPart协议 (本文提供全部源码下载,请访问 https://github.com/grayprince/UploadBigFil ...

  5. Java下载https文件上传到阿里云oss服务器

    Java下载https文件上传到阿里云oss服务器 今天做了一个从Https链接中下载音频并且上传到OSS服务器,记录一下希望大家也少走弯路. 一共两个类: 1 .实现自己的证书信任管理器类 /** ...

  6. 【Java】JavaWeb文件上传和下载

    文件上传和下载在web应用中非常普遍,要在jsp环境中实现文件上传功能是非常容易的,因为网上有许多用java开发的文件上传组件,本文以commons-fileupload组件为例,为jsp应用添加文件 ...

  7. java+web+大文件上传下载

    文件上传是最古老的互联网操作之一,20多年来几乎没有怎么变化,还是操作麻烦.缺乏交互.用户体验差. 一.前端代码 英国程序员Remy Sharp总结了这些新的接口 ,本文在他的基础之上,讨论在前端采用 ...

  8. Java结合WebUploader文件上传

    之前自己写小项目的时候也碰到过文件上传的问题,没有找到很好的解决方案.虽然之前网找各种解决方案的时候也看到过WebUploader,但没有进一步深究.这次稍微深入了解了些,这里也做个小结. 简单的文件 ...

  9. Java Web(十一) 文件上传与下载

    文件上传 上传的准备工作 表单method必须为post 提供file组件 设置form标签的enctype属性为multipart/form-data,如果没有设置enctype属性,浏览器是无法将 ...

随机推荐

  1. DateHelper.cs日期时间操作辅助类C#

    //==================================================================== //** Copyright © classbao.com ...

  2. (转)ORA-12514 TNS 监听程序当前无法识别连接描述符中请求服务 的解决方法

    早上同事用PL/SQL连接虚拟机中的Oracle数据库,发现又报了"ORA-12514 TNS 监听程序当前无法识别连接描述符中请求服务"错误,帮其解决后,发现很多人遇到过这样的问 ...

  3. 改变你代码习惯的ES6

    最近读阮一峰老师的ES6标准入门,让我感觉到了ES6的强大之处,读书之余整理了一些笔记,因为边读边记录的,所以可能会比较杂乱. ECMAScript和Javascript的关系 1996年11月,Ja ...

  4. 用java单例模式实现面板切换

    1.首先介绍一下什么是单例模式: java单例模式是一种常见的设计模式,那么我们先看看懒汉模式: public class Singleton_ { //设为私有方法,防止被外部类引用或实例 priv ...

  5. [Android Studio]SQLScout插件安装破解

    以下内容为原创,欢迎转载,转载请注明 来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/5972138.html [Android Studio]SQLS ...

  6. button自适应宽度 并根据屏幕宽自动换行排列

    这是一个封装好的类TagListView, 1. 只需要调用两个方法 设置宽度,间距,边距 并赋给它需要显示的字符串数组; 2. 遵循tagListView的协议, 并实现返回buttonView的方 ...

  7. Genymotion报Unable to load virtualbox engine错误

  8. 超简单,spring boot 添加mybatis

    看了很多人写的博客,要么太复杂,要么没有添加xml的方式,自己亲自配置了一下,供各位参考. 项目截图 1.添加pom文件 <!-- 设置mybatis --> <dependency ...

  9. Lambda表达式的诞生过程

    这是一篇很经典的文章,解决了工作中一些使用过但是又不太明白的知识点,今天终于弄明白了.花了一晚上重新整的,坚决要分享出来!!! 那得从很久很久以前说起了,记得那个时候... 懵懂的记得从前有个叫委托的 ...

  10. JavaScript—从数组的indexOf方法深入——Object的Property机制。

    在js中,可以说万物皆对象(object),一个数组也是一个对象(array). 很多对象都有很多很方便的方法 比如数组的push,concat,slice等等,但是如果一些对象,它没有实现这些方法, ...