0

クライアント側からアップロードしようとすると、403が表示され続けます。バケツに条件がないためですか?アクセスキー、署名、ポリシーなしでキーを指定するだけで、うまくアップロードできます。rails、carrierwave-direct、jqueryファイルのアップロードでクライアント側のs3にファイルをアップロード

バケットポリシー:(局部開発であることにオープン)

{ 
    "Version": "2012-10-17", 
    "Statement": [ 
     { 
      "Sid": "AddPerm", 
      "Effect": "Allow", 
      "Principal": "*", 
      "Action": "s3:*", 
      "Resource": "arn:aws:s3:::example/*" 
     } 
    ] 
} 

CORS

<?xml version="1.0" encoding="UTF-8"?> 
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/"> 
    <CORSRule> 
     <AllowedOrigin>*</AllowedOrigin> 
     <AllowedMethod>GET</AllowedMethod> 
     <AllowedMethod>PUT</AllowedMethod> 
     <AllowedMethod>POST</AllowedMethod> 
     <AllowedMethod>DELETE</AllowedMethod> 
     <AllowedHeader>*</AllowedHeader> 
    </CORSRule> 
</CORSConfiguration> 

署名生成

///whats returned - in controller 

    string_to_sign 
    set_s3_direct_post(photo) 
    render :json => { 
     :policy => @policy, 
     :signature => sig, 
     :key => Rails.application.secrets.aws_access_key_id, 
     :success=>true, 
     :store=> photo.photo.store_dir, 
     :time => @time_policy, 
     :time_date => @date_stamp, 
     :form_data => @s3_direct_post 
    } 

------------------------------------------------------------------ 
    private 

    def string_to_sign 
    @time = Time.now.utc 
    @time_policy = @time.strftime('%Y%m%dT000000Z') 
    @date_stamp = @time.strftime('%Y%m%d') 

    ret = {"expiration" => 1.day.from_now.utc.xmlschema, 
      "conditions" => [ 
       {"bucket" => Rails.application.secrets.aws_bucket}, 
       {"x-amz-credential": "#{Rails.application.secrets.aws_access_key_id}/#{@date_stamp}/us-west-2/s3/aws4_request"}, 
       {"x-amz-algorithm": "AWS4-HMAC-SHA256"}, 
       {"x-amz-date": @time_policy }, 
      ] 
      } 

     @policy = Base64.encode64(ret.to_json).gsub(/\n/,'').gsub(/\r/,'') 

    end 

    def getSignatureKey 
     kDate = OpenSSL::HMAC.digest('sha256', ("AWS4" + Rails.application.secrets.aws_secret_access_key), @date_stamp) 
     kRegion = OpenSSL::HMAC.digest('sha256', kDate, 'us-west-2') 
     kService = OpenSSL::HMAC.digest('sha256', kRegion, 's3') 
     kSigning = OpenSSL::HMAC.digest('sha256', kService, "aws4_request") 
    end 

    def sig 
     sig = OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), getSignatureKey, @policy).gsub(/\n|\r/, '') 
    end 

クライアント:

var self=this; 
    $(`#song-upload`).fileupload({ 
     url: `https://${self._backend.BUCKET}.s3.amazonaws.com`, 
     dataType: 'json', 
     add: function (e, data) { 
      var data_add = data; 
      $.ajax({ 
      url: `${self._backend.SERVER_URL}/api/photo/new`, 
      data: {'authorization': `Bearer ${self._auth.isLoggedIn.getCookie('_auth')}`, post_type: 1, file_name:this.file_name}, 
      type: 'POST', 
      success: function(data) { 
       if(data.success){ 
       console.log(data); 
       self.key = data.key; 
       self.policy = data.policy; 
       self.signature = data.signature; 
       self.store_dir = data.store; 
       self.upload_time = data.time; 
       self.upload_date = data.time_date; 
       data_add.submit(); 
       } 
      } 
      }); 
     }, 
     submit: function (e, data) { 
      data.formData = {key:`${self.store_dir}/${self.file_name}`,AWSAccessKeyId: self.key, "Policy":self.policy, "x-amz-algorithm":"AWS4-HMAC-SHA256","Signature":self.signature,"x-amz-credential":`${self.key}/${self.upload_date}/us-west-2/s3/aws4_request`, "x-amz-date":self.upload_time}; 
     }, 
     progress: function (e, data) { 
      var progress = Math.floor(((parseInt(data.loaded)*0.9)/(parseInt(data.total))) * 100); 
      $('#inner-progress').css({'transform':`translateX(${progress}%)`}); 
      $('#progress-text').text(progress); 
     }, 
     done: function (e, data) { 
      $('#inner-progress').css({'transform':`translateX(100%)`}); 
      $('#progress-text').text(100); 
      if(e) console.log(e); 
     } 
    }); 
+0

過去にこれを行いました。私はHerokuからこの記事をフォローしていました。 https://devcenter.heroku.com/articles/direct-to-s3-image-uploads-in-railsまた、同じことについてhttp://stackoverflow.com/a/34830257/3962760の回答を参照することもできます。 –

+0

文書をピークに達しました。それは本当によく見えます。私は朝にそれを通過します。ありがとう。また、s3で認証なしのファイルをアップロードできる理由を知っていますか?それは欠落した政策条件ですか? –

+0

重要なことは、CORS設定と、正しい資格情報を持つS3バケットオブジェクトです。これらの2つのことが適切であれば、事前に署名されたURLを簡単に取得できます。そして一度あなたがそれを持っていれば、他の認証は必要ありません。 –

答えて

0

誰かがこれを持っていて、JavaScriptアップロードをしようとしている場合は、見つかったhtmlファイルに値を差し込んでみてください。here Amazonは、403の応答ではなく、実際のエラーを教えてくれます。

base64の設定で["starts-with", "$key", "uploads"]が見つかりませんでした。

バケツ設定::ここで

は私の最後の構成だ

{ 
    "Version": "2012-10-17", 
    "Statement": [ 
     { 
      "Sid": "Allow Get", 
      "Effect": "Allow", 
      "Principal": "*", 
      "Action": "s3:GetObject", 
      "Resource": "arn:aws:s3:::example-development/*" 
     }, 
     { 
      "Sid": "AddPerm", 
      "Effect": "Allow", 
      "Principal": { 
       "AWS": "arn:aws:iam::123456789:user/example" 
      }, 
      "Action": "s3:*", 
      "Resource": ["arn:aws:s3:::example-development/*","arn:aws:s3:::example-development"] 
     } 
    ] 
} 

バケツ

<?xml version="1.0" encoding="UTF-8"?> 
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/"> 
    <CORSRule> 
     <AllowedOrigin>*</AllowedOrigin> 
     <AllowedMethod>GET</AllowedMethod> 
     <AllowedMethod>PUT</AllowedMethod> 
     <AllowedMethod>POST</AllowedMethod> 
     <AllowedMethod>DELETE</AllowedMethod> 
     <AllowedHeader>*</AllowedHeader> 
    </CORSRule> 
</CORSConfiguration> 

バックエンド:

 string_to_sign 
     set_s3_direct_post(song) 
     render :json => { 
       :policy => @policy, 
       :signature => sig, 
       :key => Rails.application.secrets.aws_access_key_id, 
       :success=>true, 
       :store=> song.song.store_dir, 
       :time => @time_policy, 
       :time_date => @date_stamp, 
       :form_data => @s3_direct_post 
     } 

def string_to_sign 

    @time = Time.now.utc 
    @time_policy = @time.strftime('%Y%m%dT000000Z') 
    @date_stamp = @time.strftime('%Y%m%d') 

    ret = {"expiration" => 10.hours.from_now.utc.iso8601, 
      "conditions" => [ 
       {"bucket" => 'waydope-development'}, 
       {"x-amz-credential": "#{Rails.application.secrets.aws_access_key_id}/#{@date_stamp}/us-west-2/s3/aws4_request"}, 
       {"x-amz-algorithm": "AWS4-HMAC-SHA256"}, 
       {"x-amz-date": @time_policy }, 
       ["starts-with", "$key", "uploads"] 
      ] 
      } 
    @policy = Base64.encode64(ret.to_json).gsub(/\n|\r/, '') 

end 

def getSignatureKey 
     kDate = OpenSSL::HMAC.digest('sha256', ("AWS4" + Rails.application.secrets.aws_secret_access_key), @date_stamp) 
     kRegion = OpenSSL::HMAC.digest('sha256', kDate, 'us-west-2') 
     kService = OpenSSL::HMAC.digest('sha256', kRegion, 's3') 
     kSigning = OpenSSL::HMAC.digest('sha256', kService, "aws4_request") 
    end 

def sig 
     # sig = Base64.encode64(OpenSSL::HMAC.digest('sha256', getSignatureKey, @policy)).gsub(/\n|\r/, '') 
     sig = OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), getSignatureKey, @policy).gsub(/\n|\r/, '') 
end 

クライアント:

var self=this; 
    $(`#song-upload`).fileupload({ 
     url: `https://${self._backend.BUCKET}.s3.amazonaws.com`, 
     dataType: 'multipart/form-data', 
     add: function (e, data) { 
      var data_add = data; 
      $.ajax({ 
      url: `${self._backend.SERVER_URL}/api/music/new`, 
      data: {'authorization': `Bearer ${self._auth.isLoggedIn.getCookie('_waydope')}`, post_type: 1, file_name:this.file_name}, 
      type: 'POST', 
      success: function(data) { 
       if(data.success){ 
       console.log(data); 
       self.key = data.key; 
       self.policy = data.policy; 
       self.signature = data.signature; 
       self.store_dir = data.store; 
       self.upload_time = data.time; 
       self.upload_date = data.time_date; 
       data_add.submit(); 
       } 
      } 
      }); 
     }, 
     submit: function (e, data) { 
      data.formData = {key:`${self.store_dir}/${self.file_name}`, "Policy":self.policy,"X-Amz-Signature":self.signature,"X-Amz-Credential":`${self.key}/${self.upload_date}/us-west-2/s3/aws4_request`,"X-Amz-Algorithm":"AWS4-HMAC-SHA256", "X-Amz-Date":self.upload_time, "acl": "public-read"}; 
     }, 
     progress: function (e, data) { 
      var progress = Math.floor(((parseInt(data.loaded)*0.9)/(parseInt(data.total))) * 100); 
      $('#inner-progress').css({'transform':`translateX(${progress}%)`}); 
      $('#progress-text').text(progress); 
     }, 
     done: function (e, data) { 
      $('#inner-progress').css({'transform':`translateX(100%)`}); 
      $('#progress-text').text(100); 
      if(e) console.log(e); 
     } 
    }); 
+0

これらのAWS S3リクエストパラメータを手作業で生成する必要はないことに注意してください。公式の ' aws-sdk' gemを使ってそれらを生成してください:http://docs.aws.amazon.com/sdkforruby/api/Aws/S3/Object.html#presigned_post-instance_method –

+0

私は間違って使っているかもしれません物事は間違っていますが)私が見たものから、資格と方針は宝石から返されません。 Herokuは[ブラウザのアップロードで宝石を使うのに良いガイドがある](https://devcenter.heroku.com/articles/direct-to-s3-image-uploads-in-rails) –

+1

私はそう思う。 -sdk'バージョン2.7.11私の次のスニペットは 'policy'と' x-amz-credential'の両方のパラメータを返します: 'Aws :: S3 :: Resource.new(access_key_id:" abc "、secret_access_key:" xyz "地域: "eu-west-1")バケット( "バケット")オブジェクト( "foo")。presigned_post.fields' –

関連する問題