3

ファイルを AWS S3 バケットにアップロードするために署名付き POST を実行したいのですが、これは Go でどのように行われますか?

これは、PUT を使用した署名済みアップロードとは異なることに注意してください。

4

4 に答える 4

5

したがって、他の人を助けるために、私は自分で質問に答え、同じ問題を抱えている可能性のある他の人を助けるためのコードを提供します.

署名済みの POST フォームをレンダリングする Google App Engine のサンプル Web アプリは、こちらにあります

Goで署名済みの POST を実行するために作成した小さなライブラリ

つまり、署名付き POST をパブリック読み取り Amazon S3 バケットに実行するには、次のことを行う必要があります。

1. パブリック ダウンロードのみを許可するように S3 バケットを構成します。

パブリック読み取りのみを許可するバケット ポリシーの例。

{
    "Version": "2012-10-17",
    "Id": "akjsdhakshfjlashdf",
    "Statement": [
        {
            "Sid": "kjahsdkajhsdkjasda",
            "Effect": "Allow",
            "Principal": {
                "AWS": "*"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::BUCKETNAMEHERE/*"
        }
    ]
}

2. アップロードを許可する HTTP POST のポリシーを作成します。

AWS S3 ドキュメント

特定のキーを特定のバケットにアップロードし、パブリック読み取りアクセスを許可する有効期限付きの POST ポリシー テンプレートの例。

{ "expiration": "%s",
    "conditions": [
        {"bucket": "%s"},
        ["starts-with", "$key", "%s"],
        {"acl": "public-read"},

        {"x-amz-credential": "%s"},
        {"x-amz-algorithm": "AWS4-HMAC-SHA256"},
        {"x-amz-date": "%s" }
    ]
}

3. S3 バケット所有者の認証情報を使用してポリシーを生成し、署名します。

AWS ドキュメント

  • 有効期限、バケット、キー、資格情報、および日付に正しい値を入力します。
  • base64 でポリシーをエンコードします。
  • HMAC-SHA256 署名を取得するためのポリシー。
  • 署名を 16 進エンコードします。

4. マルチパート フォーム データの構築と POST

AWS S3 ドキュメント

上記のリンクで説明されているように、HTML フォームを生成し、正しいマルチパート フォーム データ リクエストを自動的に取得します。

Goでこれを手動でやりたかったので、その方法を次に示します。

どちらの方法でも、ステップ 2 と 3 で作成した POST ポリシーで指定されているすべての部分を提供する必要があります。必須フィールド (ポリシーにないもの) を除いて、リクエストに追加フィールドを含めることもできません。

フィールドの順序も指定されており、それらはすべて HTTP POST 要求のマルチパート フィールドです。

func Upload(url string, fields Fields) error {
    var b bytes.Buffer
    w := multipart.NewWriter(&b)
    for _, f := range fields {
            fw, err := w.CreateFormField(f.Key)
            if err != nil {
                    return err
            }
            if _, err := fw.Write([]byte(f.Value)); err != nil {
                    return err
            }
    }
    w.Close()

    req, err := http.NewRequest("POST", url, &b)
    if err != nil {
            return err
    }
    req.Header.Set("Content-Type", w.FormDataContentType())

    client := &http.Client{}
    res, err := client.Do(req)
    if err != nil {
            return err
    }
    if res.StatusCode != http.StatusOK {
            err = fmt.Errorf("bad status: %s", res.Status)
    }
    return nil
}
于 2015-09-08T09:10:47.447 に答える
4

これは、 https://github.com/minio/minio-goからの別のアプローチであり、 署名付きの投稿ポリシーを生成する完全なプログラムによる方法が必要な場合があります。

package main

import (
    "fmt"
    "log"
    "time"

    "github.com/minio/minio-go"
)

func main() {
    policy := minio.NewPostPolicy()
    policy.SetKey("myobject")
    policy.SetBucket("mybucket")
    policy.SetExpires(time.Now().UTC().AddDate(0, 0, 10)) // expires in 10 days
    config := minio.Config{
        AccessKeyID:     "YOUR-ACCESS-KEY-HERE",
        SecretAccessKey: "YOUR-PASSWORD-HERE",
        Endpoint:        "https://s3.amazonaws.com",
    }
    s3Client, err := minio.New(config)
    if err != nil {
        log.Fatalln(err)
    }
    m, err := s3Client.PresignedPostPolicy(policy)
    if err != nil {
        fmt.Println(err)
        return
    }
    fmt.Printf("curl ")
    for k, v := range m {
        fmt.Printf("-F %s=%s ", k, v)
    }
    fmt.Printf("-F file=@/etc/bashrc ")
    fmt.Printf(config.Endpoint + "/mybucket\n")
}

ステップ1:

    policy := minio.NewPostPolicy()
    policy.SetKey("myobject")
    policy.SetBucket("mybucket")
    policy.SetExpires(time.Now().UTC().AddDate(0, 0, 10)) // expires in 10 days

新しいポリシー構造をインスタンス化します。このポリシー構造は次のメソッドを実装します。

func NewPostPolicy() *PostPolicy
func (p *PostPolicy) SetBucket(bucket string) error
func (p *PostPolicy) SetContentLength(min, max int) error
func (p *PostPolicy) SetContentType(contentType string) error
func (p *PostPolicy) SetExpires(t time.Time) error
func (p *PostPolicy) SetKey(key string) error
func (p *PostPolicy) SetKeyStartsWith(keyStartsWith string) error
func (p PostPolicy) String() string

ステップ2:

    m, err := s3Client.PresignedPostPolicy(policy)
    if err != nil {
        fmt.Println(err)
        return
    }

PresignedPostPolicy() はPostPolicy構造を取得し、HTML フォームまたは curl コマンドで使用してデータを s3 にアップロードできる「キー/値」のマップを返します。

于 2015-11-07T00:38:56.647 に答える
2

一見すると、ブラウザベースのアップロード用に設計されたポリシーと署名が添付された状態で POST が動作するように見えます。詳細については、AWS ドキュメントを参照してください

具体的には、ポリシーを生成して署名する必要があります。次に、それらを HTML フォームに含め、それによって POST 要求に、残りの必要な情報を含めます。または、ブラウザに任せてください。

HTML フォームの POST アップロードの場合、ポリシー文字列に署名するだけです。投稿される最終的な URL は、フォームの内容によって異なります: https://bucket.s3.amazonaws.com/<depends-on-form-content>. そのため、その URL が何であるかわからないため、その URL に署名することはできません。

これは、ファイルを PUT する署名付き URL とは異なります。完全な URL を知っているため、署名できます。https://bucket.s3.amazonaws.com/known-key

適切なポリシーとパラメータを使用して POST リクエストを作成し、その方法で POST 経由でアップロードできます。ただし、事前に URL を知るには、フォームの内容を知っておく必要があります。その場合、署名付きの PUT URL を使用することもできます。

少なくとも、一見するとそう見えます...

于 2015-09-05T01:39:00.540 に答える