Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 967|回复: 0

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

[复制链接]
  • TA的每日心情
    奋斗
    前天 22:27
  • 签到天数: 787 天

    [LV.10]以坛为家III

    2049

    主题

    2107

    帖子

    72万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    722142
    发表于 2021-4-28 16:26:53 | 显示全部楼层 |阅读模式
    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

     

    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-8-30 01:36 , Processed in 0.058649 second(s), 29 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表