全部產品
Search
文件中心

Object Storage Service:Go授權訪問

更新時間:Jun 19, 2024

本文介紹如何使用STS以及簽名URL臨時授權訪問OSS資源。

重要

由於STS臨時帳號以及簽名URL均需設定有效時間長度,當您使用STS臨時帳號產生簽名URL執行相關操作(例如上傳、下載檔案)時,以最小的有效時間長度為準。例如您的STS臨時帳號的有效時間長度設定為1200秒、簽名URL設定為3600秒時,當有效時間長度超過1200秒後,您無法使用此STS臨時帳號產生的簽名URL上傳檔案。

注意事項

  • 本文以華東1(杭州)外網Endpoint為例。如果您希望通過與OSS同地區的其他阿里雲產品訪問OSS,請使用內網Endpoint。關於OSS支援的Region與Endpoint的對應關係,請參見訪問網域名稱和資料中心

  • 本文以從環境變數讀取存取憑證為例。如何配置訪問憑證,請參見配置訪問憑證

  • 本文以OSS網域名稱建立OSSClient為例。如果您希望通過自訂網域名、STS等方式建立OSSClient,請參見初始化

使用STS臨時授權

OSS可以通過阿里雲STS(Security Token Service)進行臨時授權訪問。阿里雲STS是為雲端運算使用者提供臨時存取權杖的Web服務。通過STS,您可以為第三方應用或子使用者(即使用者身份由您自己管理的使用者)頒發一個自訂時效和許可權的訪問憑證。關於STS的更多資訊,請參見STS介紹

STS的優勢如下:

  • 您無需透露您的長期密鑰(AccessKey)給第三方應用,只需產生一個存取權杖並將令牌交給第三方應用。您可以自訂這個令牌的存取權限及有效期間限。

  • 您無需關心許可權撤銷問題,存取權杖到期後自動失效。

通過STS臨時授權訪問OSS的步驟如下:

  1. 擷取臨時訪問憑證

    臨時訪問憑證包括臨時存取金鑰(AccessKey ID和AccessKey Secret)和安全性權杖(SecurityToken)。臨時訪問憑證有效時間單位為秒,最小值為900,最大值以當前角色設定的最大會話時間為準。更多資訊,請參見設定RAM角色最大會話時間

    您可以通過以下兩種方式擷取臨時訪問憑證。

    • 方式一

      通過調用STS服務的AssumeRole介面擷取臨時訪問憑證。

    • 方式二

      通過各語言STS SDK擷取臨時訪問憑證。

  2. 使用STS臨時授權訪問OSS

    • 使用STS臨時授權上傳檔案

      package main
      
      import (
          "fmt"
          "github.com/aliyun/aliyun-oss-go-sdk/oss"
          "os"
      )
      
      func main() {
          // 從環境變數中擷取臨時訪問憑證。運行本程式碼範例之前,請確保已設定環境變數OSS_ACCESS_KEY_ID、OSS_ACCESS_KEY_SECRET、OSS_SESSION_TOKEN。
          provider, err := oss.NewEnvironmentVariableCredentialsProvider()
          if err != nil {
              fmt.Println("Error:", err)
              os.Exit(-1)
          }
          // 建立OSSClient執行個體。
          // yourEndpoint填寫Bucket對應的Endpoint,以華東1(杭州)為例,填寫為https://oss-cn-hangzhou.aliyuncs.com。其它Region請按實際情況填寫。
          client, err := oss.New("yourEndpoint", "", "", oss.SetCredentialsProvider(&provider))
          if err != nil {
              fmt.Println("Error:", err)
              os.Exit(-1)
          }
          // 填寫Bucket名稱,例如examplebucket。
          bucketName := "examplebucket"
          // 填寫Object的完整路徑,完整路徑中不能包含Bucket名稱,例如exampledir/exampleobject.txt。
          objectName := "exampledir/exampleobject.txt"
          // 填寫本地檔案的完整路徑,例如D:\\localpath\\examplefile.txt。
          filepath := "D:\\localpath\\examplefile.txt"
          bucket,err := client.Bucket(bucketName)
          // 通過STS授權第三方上傳檔案。
          err = bucket.PutObjectFromFile(objectName,filepath)
          if err != nil {
              fmt.Println("Error:", err)
              os.Exit(-1)
          }
          fmt.Println("upload success")
      }
    • 使用STS臨時授權下載檔案

      package main
      
      import (
          "fmt"
          "github.com/aliyun/aliyun-oss-go-sdk/oss"
          "os"
      )
      
      func main() {
          // 從環境變數中擷取臨時訪問憑證。運行本程式碼範例之前,請確保已設定環境變數OSS_ACCESS_KEY_ID、OSS_ACCESS_KEY_SECRET、OSS_SESSION_TOKEN。
          provider, err := oss.NewEnvironmentVariableCredentialsProvider()
          if err != nil {
              fmt.Println("Error:", err)
              os.Exit(-1)
          }
          // 建立OSSClient執行個體。
          // yourEndpoint填寫Bucket對應的Endpoint,以華東1(杭州)為例,填寫為https://oss-cn-hangzhou.aliyuncs.com。其它Region請按實際情況填寫。
          client, err := oss.New("yourEndpoint", "", "", oss.SetCredentialsProvider(&provider))
          if err != nil {
              fmt.Println("Error:", err)
              os.Exit(-1)
          }
          // 填寫Bucket名稱,例如examplebucket。
          bucketName := "examplebucket"
          // 填寫Object的完整路徑,完整路徑中不能包含Bucket名稱,例如exampledir/exampleobject.txt。
          objectName := "exampledir/exampleobject.txt"
          // 填寫本地檔案的完整路徑,例如D:\\localpath\\examplefile.txt。
          filepath := "D:\\localpath\\examplefile.txt"
          bucket,err := client.Bucket(bucketName)
          // 通過STS授權第三方下載檔案。
          err = bucket.GetObjectToFile(objectName,filepath)
          if err != nil {
              fmt.Println("Error:", err)
              os.Exit(-1)
          }
          fmt.Println("download success")
      }

使用簽名URL臨時授權

注意事項

  • 產生簽名URL過程中,SDK利用本機存放區的密鑰資訊,根據特定演算法計算出簽名(signature),然後將其附加到URL上,以確保URL的有效性和安全性。這一系列計算和構造URL的操作都是在用戶端完成,不涉及網路請求到服務端。因此,產生簽名URL時不需要授予調用者特定許可權。但是,為避免第三方使用者無法對簽名URL授權的資源執行相關操作,需要確保調用產生簽名URL介面的身份主體被授予對應的許可權。

    例如,通過簽名URL上傳檔案時,需要授予oss:PutObject許可權。通過簽名URL下載或預覽檔案時,需要授予oss:GetObject許可權。

  • 您可以將產生的簽名URL提供給訪客進行臨時訪問。產生簽名URL時,您可以自訂URL的到期時間來限制訪客的訪問時間長度。

  • 如果需要產生HTTPS協議的簽名URL,請將Endpoint中的通訊協定設定為HTTPS。

  • 通過以下樣本產生的簽名URL中如果包含特殊符號+,可能出現無法正常訪問該簽名URL的現象。如需正常訪問該簽名URL,請將簽名URL中的+替換為%2B

以下介紹使用簽名URL臨時授權的常見樣本。使用簽名URL進行臨時授權的完整代碼請參見GitHub

使用簽名URL上傳檔案

  1. 產生用於上傳的簽名URL

    package main
    
    import (
        "fmt"
        "os"
        "github.com/aliyun/aliyun-oss-go-sdk/oss"
    )
    
    func HandleError(err error) {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }
    
    func main() {
    	// 從環境變數中擷取訪問憑證。運行本程式碼範例之前,請確保已設定環境變數OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
    	provider, err := oss.NewEnvironmentVariableCredentialsProvider()
    	if err != nil {
    		fmt.Println("Error:", err)
    		os.Exit(-1)
    	}
    	// 建立OSSClient執行個體。
    	// yourEndpoint填寫Bucket對應的Endpoint,以華東1(杭州)為例,填寫為https://oss-cn-hangzhou.aliyuncs.com。其它Region請按實際情況填寫。
    	client, err := oss.New("yourEndpoint", "", "", oss.SetCredentialsProvider(&provider))
    	if err != nil {
    		fmt.Println("Error:", err)
    		os.Exit(-1)
    	}
        // 填寫Bucket名稱,例如examplebucket。
        bucketName := "examplebucket"
        // 填寫檔案完整路徑,例如exampledir/exampleobject.txt。檔案完整路徑中不能包含Bucket名稱。
        objectName := "exampledir/exampleobject.txt"
        bucket, err := client.Bucket(bucketName)
        if err != nil {
            HandleError(err)
        }
        // 產生用於上傳的簽名URL,並指定簽名URL的有效時間為60秒。
        signedURL, err := bucket.SignURL(objectName, oss.HTTPPut, 60)
        if err != nil {
            HandleError(err)
        }
    
        // 如果要在前端使用帶選擇性參數的簽名URL,請確保在服務端產生該簽名URL時設定的ContentType與在前端使用時設定的ContentType一致。
        options := []oss.Option{
            oss.Meta("myprop", "mypropval"),
            oss.ContentType("text/plain"),
        }
        
        signedURL, err = bucket.SignURL(objectName, oss.HTTPPut, 60, options...)
        if err != nil {
            HandleError(err)
        }
        fmt.Printf("Sign Url:%s\n", signedURL)
    }
  2. 通過簽名URL上傳檔案

    您可以參考移動端Android SDK通過簽名URL上傳檔案。更多資訊,請參見通過簽名URL上傳檔案

使用簽名URL臨時授權分區上傳

當您希望使用簽名URL以分區上傳的方式上傳大檔案到OSS時,您需要先初始化分區上傳,然後把每一個分區產生一個對應的上傳簽名URL,並返回給第三方應用。第三方應用可以使用這些簽名URL上傳所有的分區資訊,然後合并分區來達到通過簽名URL實現分區上傳的目的。

以下代碼用於產生分區上傳的簽名URL,並使用簽名URL臨時授權分區上傳。

package main

import (
    "crypto/md5"
    "encoding/base64"
    "fmt"
    "github.com/aliyun/aliyun-oss-go-sdk/oss"
    "github.com/aliyun/aliyun-oss-go-sdk/sample"
    "io/ioutil"
    "os"
    "strconv"
)

func main() {
    // 從環境變數中擷取訪問憑證。運行本程式碼範例之前,請確保已設定環境變數OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
    provider, err := oss.NewEnvironmentVariableCredentialsProvider()
    if err != nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }
    // 建立OSSClient執行個體。
    // yourEndpoint填寫Bucket對應的Endpoint,以華東1(杭州)為例,填寫為https://oss-cn-hangzhou.aliyuncs.com。其它Region請按實際情況填寫。
    client, err := oss.New("yourEndpoint", "", "", oss.SetCredentialsProvider(&provider))
    if err != nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }
    bucketName := "bucket_name"

    bucket,err := client.Bucket(bucketName)
    if err != nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }
    // 填寫Object完整路徑。Object完整路徑中不能包含Bucket名稱。
    objectName := "example.txt"
    // 填寫本地檔案的完整路徑。如果未指定本地路徑,則預設從樣本程式所屬專案對應本地路徑中上傳檔案。
    localFile := "D:\\download\\demo.txt"

    // 將本地檔案分區,且指定分區數量為3。
    chunks, err := oss.SplitFileByPartNum(localFile, 3)
    fd, err := os.Open(localFile)
    defer fd.Close()
    // 步驟1:初始化一個分區上傳事件,並指定儲存類型為標準儲存。
    imur, err := bucket.InitiateMultipartUpload(objectName)
    // 步驟2:上傳分區。
    var options []oss.Option

    for _, chunk := range chunks {
        // MD5加密驗證。
        // buf := make([]byte, chunk.Size)
        // fd.ReadAt(buf,chunk.Size)
        // sum := md5.Sum(buf)
        // b64 := base64.StdEncoding.EncodeToString(sum[:])
        // options = []oss.Option{
        //     oss.ContentMD5(b64),
        // }

        options = append(options, oss.AddParam("partNumber", strconv.Itoa(chunk.Number)))
        options = append(options, oss.AddParam("uploadId", imur.UploadID))
        // 產生簽名URL。
        signedURL, err := bucket.SignURL(objectName, oss.HTTPPut, 60,options)
        if err != nil {
            fmt.Println("Error:", err)
            os.Exit(-1)
        }
        fmt.Printf("簽名url:%s\n", signedURL)
    }
    
    lsRes, err := bucket.ListUploadedParts(imur)
    if err != nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }

    // 遍曆分區,並填充ETag值。
    var parts []oss.UploadPart
    for _, p := range lsRes.UploadedParts {
        parts = append(parts, oss.UploadPart{XMLName: p.XMLName, PartNumber: p.PartNumber, ETag: p.ETag})
    }

    // 步驟3:完成分區上傳。
    _, err := bucket.CompleteMultipartUpload(imur, parts)
    if err != nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }
    fmt.Println("上傳成功")
}

使用簽名URL下載檔案

  1. 產生用於下載的簽名URL

    package main
    
    import (
        "fmt"
        "github.com/aliyun/aliyun-oss-go-sdk/oss"
        "os"
    )
    
    func HandleError(err error) {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }
    
    func main() {
        // 從環境變數中擷取訪問憑證。運行本程式碼範例之前,請確保已設定環境變數OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
        provider, err := oss.NewEnvironmentVariableCredentialsProvider()
        if err != nil {
            fmt.Println("Error:", err)
            os.Exit(-1)
        }
        // 建立OSSClient執行個體。
        // yourEndpoint填寫Bucket對應的Endpoint,以華東1(杭州)為例,填寫為https://oss-cn-hangzhou.aliyuncs.com。其它Region請按實際情況填寫。
        client, err := oss.New("yourEndpoint", "", "", oss.SetCredentialsProvider(&provider))
        if err != nil {
            fmt.Println("Error:", err)
            os.Exit(-1)
        }
    
        // 填寫Bucket名稱,例如examplebucket。
        bucketName := "examplebucket"
        // 填寫檔案完整路徑,例如exampledir/exampleobject.txt。檔案完整路徑中不能包含Bucket名稱。
        objectName := "exampledir/exampleobject.txt"
        // 將Object下載到本地檔案,並儲存到指定的本地路徑中。如果指定的本地檔案存在會覆蓋,不存在則建立。
        bucket, err := client.Bucket(bucketName)
        if err != nil {
            HandleError(err)
        }
    
        // 產生用於下載的簽名URL,並指定簽名URL的有效時間為60秒。
        signedURL, err := bucket.SignURL(objectName, oss.HTTPGet, 60)
        if err != nil {
            HandleError(err)
        }
        fmt.Printf("Sign Url:%s\n", signedURL)
    }
  2. 通過簽名URL下載檔案

    您可以參考移動端Android SDK通過簽名URL下載檔案。更多資訊,請參見通過簽名URL下載檔案

產生帶VersionId的簽名URL

以下代碼用於產生帶VersionId的簽名URL。

package main

import (
	"fmt"
	"github.com/aliyun/aliyun-oss-go-sdk/oss"
	"os"
)

func main() {
	// 從環境變數中擷取訪問憑證。運行本程式碼範例之前,請確保已設定環境變數OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
	provider, err := oss.NewEnvironmentVariableCredentialsProvider()
	if err != nil {
		fmt.Println("Error:", err)
		os.Exit(-1)
	}
	// 建立OSSClient執行個體。
	// yourEndpoint填寫Bucket對應的Endpoint,以華東1(杭州)為例,填寫為https://oss-cn-hangzhou.aliyuncs.com。其它Region請按實際情況填寫。
	client, err := oss.New("yourEndpoint", "", "", oss.SetCredentialsProvider(&provider))
	if err != nil {
		fmt.Println("Error:", err)
		os.Exit(-1)
	}
	// 填寫Bucket名稱,例如examplebucket。
	bucketName := "examplebucket"
	// 填寫Object的完整路徑,完整路徑中不能包含Bucket名稱,例如exampledir/exampleobject.txt。
	objectName := "exampledir/exampleobject.txt"
	bucket, err := client.Bucket(bucketName)
	if err != nil {
		fmt.Println("Error:", err)
		os.Exit(-1)
	}

	// 填寫Object的VersionId。
	// 產生簽名URL,並指定簽名URL的有效時間為60秒。
	signedURL, err := bucket.SignURL(objectName, oss.HTTPGet, 60, oss.VersionId("CAEQEhiBgIDmgPf8mxgiIDA1YjZlNDIxY2ZmMzQ1MmU5MTM1Y2M4Yzk4******"))
	if err != nil {
		fmt.Println("Error:", err)
		os.Exit(-1)
	}

	fmt.Printf("Sign Url:%s\n", signedURL)
}