全部產品
Search
文件中心

Object Storage Service:C授權訪問

更新時間:Jun 08, 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憑證建構簽章請求。

    • 上傳檔案

      #include "oss_api.h"
      #include "aos_http_io.h"
      /* yourEndpoint填寫Bucket所在地區對應的Endpoint。以華東1(杭州)為例,Endpoint填寫為https://oss-cn-hangzhou.aliyuncs.com。*/
      const char *endpoint = "yourEndpoint";
      /* 運行本程式碼範例之前,請確保已使用STS服務擷取的臨時存取金鑰設定環境變數YOUR_ACCESS_KEY_ID和YOUR_ACCESS_KEY_SECRET。*/  
      const char *access_key_id = getenv("OSS_ACCESS_KEY_ID");
      const char *access_key_secret = getenv("OSS_ACCESS_KEY_SECRET");
      /* 從STS服務擷取的安全性權杖(SecurityToken)。*/
      const char *sts_token = "yourStsToken";
      /* 填寫Bucket名稱,例如examplebucket。*/
      const char *bucket_name = "examplebucket";
      /* 填寫Object完整路徑,完整路徑中不能包含Bucket名稱,例如exampledir/exampleobject.txt。*/
      const char *object_name = "exampledir/exampleobject.txt";
      const char *object_content = "More than just cloud.";
      
      void init_options(oss_request_options_t *options)
      {
          options->config = oss_config_create(options->pool);
          /* 用char*類型的字串初始化aos_string_t類型。*/
          aos_str_set(&options->config->endpoint, endpoint);
          aos_str_set(&options->config->access_key_id, access_key_id);
          aos_str_set(&options->config->access_key_secret, access_key_secret);
          aos_str_set(&options->config->sts_token, sts_token);
          /* 是否使用CNAME訪問OSS服務。0表示不使用。*/
          options->config->is_cname = 0;
          /* 設定網路相關參數,例如逾時時間等。*/
          options->ctl = aos_http_controller_create(options->pool, 0);
      }
      
      int main(int argc, char *argv[])
      {
          /* 在程式入口調用aos_http_io_initialize方法來初始化網路、記憶體等全域資源。*/
          if (aos_http_io_initialize(NULL, 0) != AOSE_OK) {
              exit(1);
          }
      
          /* 用於記憶體管理的記憶體池(pool),等價於apr_pool_t。其實現代碼在apr庫中。*/
          aos_pool_t *pool;
          /* 重新建立一個記憶體池,第二個參數是NULL,表示沒有繼承其他記憶體池。*/
          aos_pool_create(&pool, NULL);
          /* 建立並初始化options,該參數包括endpoint、access_key_id、acces_key_secret、is_cname、curl等全域配置資訊。*/
          oss_request_options_t *oss_client_options;
          /* 在記憶體池中分配記憶體給options。*/
          oss_client_options = oss_request_options_create(pool);
          /* 初始化Client的選項oss_client_options。*/
          init_options(oss_client_options);
      
          /* 初始化參數。*/
          aos_string_t bucket;
          aos_string_t object;
          aos_list_t buffer;
          aos_buf_t *content = NULL;
          aos_table_t *headers = NULL;
          aos_table_t *resp_headers = NULL; 
          aos_status_t *resp_status = NULL; 
          /* 將類型為char*的資料賦值給bucket。*/
          aos_str_set(&bucket, bucket_name);
          aos_str_set(&object, object_name);
      
          aos_list_init(&buffer);
          content = aos_buf_pack(oss_client_options->pool, object_content, strlen(object_content));
          aos_list_add_tail(&content->node, &buffer);
      
          /* 上傳檔案。*/
          resp_status = oss_put_object_from_buffer(oss_client_options, &bucket, &object, &buffer, headers, &resp_headers);
          /* 判斷檔案是否上傳成功。*/
          if (aos_status_is_ok(resp_status)) {
              printf("put object from buffer succeeded\n");
          } else {
              printf("put object from buffer failed\n");      
          }    
      
          /* 釋放記憶體池,相當於釋放了請求過程中各資源分派的記憶體。*/
          aos_pool_destroy(pool);
      
          /* 釋放之前分配的全域資源。*/
          aos_http_io_deinitialize();
      
          return 0;
      }            
    • 下載檔案

      #include "oss_api.h"
      #include "aos_http_io.h"
      /* yourEndpoint填寫Bucket所在地區對應的Endpoint。以華東1(杭州)為例,Endpoint填寫為https://oss-cn-hangzhou.aliyuncs.com。*/
      const char *endpoint = "yourEndpoint";
      /* 從環境變數中擷取訪問憑證。運行本程式碼範例之前,請確保已設定環境變數OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。*/  
      const char *access_key_id = getenv("OSS_ACCESS_KEY_ID");
      const char *access_key_secret = getenv("OSS_ACCESS_KEY_SECRET");
      /* 從STS服務擷取的安全性權杖(SecurityToken)。*/
      const char *sts_token = "yourStsToken";
      /* 填寫Bucket名稱,例如examplebucket。*/
      const char *bucket_name = "examplebucket";
      /* 填寫Object完整路徑,完整路徑中不能包含Bucket名稱,例如exampledir/exampleobject.txt。*/
      const char *object_name = "exampledir/exampleobject.txt";
      void init_options(oss_request_options_t *options)
      {
          options->config = oss_config_create(options->pool);
          /* 用char*類型的字串初始化aos_string_t類型。*/
          aos_str_set(&options->config->endpoint, endpoint);
          aos_str_set(&options->config->access_key_id, access_key_id);
          aos_str_set(&options->config->access_key_secret, access_key_secret);
          aos_str_set(&options->config->sts_token, sts_token);
          /* 是否使用了CNAME。0表示不使用。*/
          options->config->is_cname = 0;
          /* 用於設定網路相關參數,比如逾時時間等。*/
          options->ctl = aos_http_controller_create(options->pool, 0);
      }
      int main(int argc, char *argv[])
      {
          /* 在程式入口調用aos_http_io_initialize方法來初始化網路、記憶體等全域資源。*/
          if (aos_http_io_initialize(NULL, 0) != AOSE_OK) {
              exit(1);
          }
          /* 用於記憶體管理的記憶體池(pool),等價於apr_pool_t。其實現代碼在apr庫中。*/
          aos_pool_t *pool;
          /* 重新建立一個記憶體池,第二個參數是NULL,表示沒有繼承其它記憶體池。*/
          aos_pool_create(&pool, NULL);
          /* 建立並初始化options,該參數包括endpoint、access_key_id、acces_key_secret、is_cname、curl等全域配置資訊。*/
          oss_request_options_t *oss_client_options;
          /* 在記憶體池中分配記憶體給options。*/
          oss_client_options = oss_request_options_create(pool);
          /* 初始化Client的選項oss_client_options。*/
          init_options(oss_client_options);
          /* 初始化參數。*/
          aos_string_t bucket;
          aos_string_t object;
          aos_list_t buffer;
          aos_buf_t *content = NULL;
          aos_table_t *params = NULL;
          aos_table_t *headers = NULL;
          aos_table_t *resp_headers = NULL; 
          aos_status_t *resp_status = NULL; 
          char *buf = NULL;
          int64_t len = 0;
          int64_t size = 0;
          int64_t pos = 0;
          aos_str_set(&bucket, bucket_name);
          aos_str_set(&object, object_name);
          aos_list_init(&buffer);
          /* 下載檔案到本地記憶體。*/
          resp_status = oss_get_object_to_buffer(oss_client_options, &bucket, &object, 
                                       headers, params, &buffer, &resp_headers);
          if (aos_status_is_ok(resp_status)) {
              printf("get object to buffer succeeded\n");
              /* 將下載內容拷貝到buffer中。*/
              len = aos_buf_list_len(&buffer);
              buf = aos_pcalloc(pool, len + 1);
              buf[len] = '\0';
              aos_list_for_each_entry(aos_buf_t, content, &buffer, node) {
              size = aos_buf_size(content);
                  memcpy(buf + pos, content->pos, size);
                  pos += size;
              }
          }
          else {
              printf("get object to buffer failed\n");  
          }
          /* 釋放記憶體池,相當於釋放了請求過程中各資源分派的記憶體。*/
          aos_pool_destroy(pool);
          /* 釋放之前分配的全域資源。*/
          aos_http_io_deinitialize();
          return 0;
      }

使用簽名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上傳檔案

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

    #include "oss_api.h"
    #include "aos_http_io.h"
    /* yourEndpoint填寫Bucket所在地區對應的Endpoint。以華東1(杭州)為例,Endpoint填寫為https://oss-cn-hangzhou.aliyuncs.com。*/
    const char *endpoint = "yourEndpoint";
    
    /* 填寫Bucket名稱,例如examplebucket。*/
    const char *bucket_name = "examplebucket";
    /* 填寫Object完整路徑,完整路徑中不能包含Bucket名稱,例如exampledir/exampleobject.txt。*/
    const char *object_name = "exampledir/exampleobject.txt";
    /* 填寫本地檔案的完整路徑。*/
    const char *local_filename = "yourLocalFilename";
    void init_options(oss_request_options_t *options)
    {
        options->config = oss_config_create(options->pool);
        /* 用char*類型的字串初始化aos_string_t類型。*/
        aos_str_set(&options->config->endpoint, endpoint);
        /* 從環境變數中擷取訪問憑證。運行本程式碼範例之前,請確保已設定環境變數OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。*/
        aos_str_set(&options->config->access_key_id, getenv("OSS_ACCESS_KEY_ID"));
        aos_str_set(&options->config->access_key_secret, getenv("OSS_ACCESS_KEY_SECRET"));
        /* 是否使用CNAME訪問OSS服務。0表示不使用。*/
        options->config->is_cname = 0;
        /* 設定網路相關參數,例如逾時時間等。*/
        options->ctl = aos_http_controller_create(options->pool, 0);
    }
    int main(int argc, char *argv[])
    {
        /* 在程式入口調用aos_http_io_initialize方法來初始化網路、記憶體等全域資源。*/
        if (aos_http_io_initialize(NULL, 0) != AOSE_OK) {
            exit(1);
        }
        /* 用於記憶體管理的記憶體池(pool),等價於apr_pool_t。其實現代碼在apr庫中。*/
        aos_pool_t *pool;
        /* 重新建立一個記憶體池,第二個參數是NULL,表示沒有繼承其它記憶體池。*/
        aos_pool_create(&pool, NULL);
        /* 建立並初始化options,該參數包括endpoint、access_key_id、acces_key_secret、is_cname、curl等全域配置資訊。*/
        oss_request_options_t *oss_client_options;
        /* 在記憶體池中分配記憶體給options。*/
        oss_client_options = oss_request_options_create(pool);
        /* 初始化Client的選項oss_client_options。*/
        init_options(oss_client_options);
        /* 初始化參數。*/
        aos_string_t bucket;
        aos_string_t object;
        aos_string_t file;    
        aos_http_request_t *req;
        apr_time_t now;
        char *url_str;
        aos_string_t url;
        int64_t expire_time; 
        int one_hour = 3600;
        aos_str_set(&bucket, bucket_name);
        aos_str_set(&object, object_name);
        aos_str_set(&file, local_filename);
        expire_time = now / 1000000 + one_hour;    
        req = aos_http_request_create(pool);
        req->method = HTTP_PUT;
        now = apr_time_now(); 
        /* 單位:微秒 */
        expire_time = now / 1000000 + one_hour;
        /* 產生簽名URL。*/
        url_str = oss_gen_signed_url(oss_client_options, &bucket, &object, expire_time, req);
        aos_str_set(&url, url_str);
        printf("臨時上傳URL: %s\n", url_str);    
        /* 釋放記憶體池,相當於釋放了請求過程中各資源分派的記憶體。*/
        aos_pool_destroy(pool);
        /* 釋放之前分配的全域資源。*/
        aos_http_io_deinitialize();
        return 0;
    }
  2. 通過簽名URL上傳檔案

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

產生簽名URL並通過簽名URL下載檔案

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

    #include "oss_api.h"
    #include "aos_http_io.h"
    /* yourEndpoint填寫Bucket所在地區對應的Endpoint。以華東1(杭州)為例,Endpoint填寫為https://oss-cn-hangzhou.aliyuncs.com。*/
    const char *endpoint = "yourEndpoint";
    /* 填寫Bucket名稱,例如examplebucket。*/
    const char *bucket_name = "examplebucket";
    /* 填寫Object完整路徑,完整路徑中不能包含Bucket名稱,例如exampledir/exampleobject.txt。*/
    const char *object_name = "exampledir/exampleobject.txt";
    /* 填寫本地檔案的完整路徑。*/
    const char *local_filename = "yourLocalFilename";
    
    void init_options(oss_request_options_t *options)
    {
        options->config = oss_config_create(options->pool);
        /* 用char*類型的字串初始化aos_string_t類型。*/
        aos_str_set(&options->config->endpoint, endpoint);
        /* 從環境變數中擷取訪問憑證。運行本程式碼範例之前,請確保已設定環境變數OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。*/
        aos_str_set(&options->config->access_key_id, getenv("OSS_ACCESS_KEY_ID"));
        aos_str_set(&options->config->access_key_secret, getenv("OSS_ACCESS_KEY_SECRET"));
        /* 是否使用CNAME訪問OSS服務。0表示不使用。*/
        options->config->is_cname = 0;
        /* 設定網路相關參數,例如逾時時間等。*/
        options->ctl = aos_http_controller_create(options->pool, 0);
    }
    int main(int argc, char *argv[])
    {
        /* 在程式入口調用aos_http_io_initialize方法來初始化網路、記憶體等全域資源。*/
        if (aos_http_io_initialize(NULL, 0) != AOSE_OK) {
            exit(1);
        }
        /* 用於記憶體管理的記憶體池(pool),等價於apr_pool_t。其實現代碼在apr庫中。*/
        aos_pool_t *pool;
        /* 重新建立一個記憶體池,第二個參數是NULL,表示沒有繼承其它記憶體池。*/
        aos_pool_create(&pool, NULL);
        /* 建立並初始化options,該參數包括endpoint、access_key_id、acces_key_secret、is_cname、curl等全域配置資訊。*/
        oss_request_options_t *oss_client_options;
        /* 在記憶體池中分配記憶體給options。*/
        oss_client_options = oss_request_options_create(pool);
        /* 初始化Client的選項oss_client_options。*/
        init_options(oss_client_options);
        /* 初始化參數。*/
        aos_string_t bucket;
        aos_string_t object;
        aos_string_t file;    
        aos_http_request_t *req;
        apr_time_t now;
        char *url_str;
        aos_string_t url;
        int64_t expire_time; 
        int one_hour = 3600;
        aos_str_set(&bucket, bucket_name);
        aos_str_set(&object, object_name);
        aos_str_set(&file, local_filename);
        expire_time = now / 1000000 + one_hour;    
        req = aos_http_request_create(pool);
        req->method = HTTP_GET;
        now = apr_time_now();  
        /* 單位:微秒 */
        expire_time = now / 1000000 + one_hour;
        /* 產生簽名URL。*/
        url_str = oss_gen_signed_url(oss_client_options, &bucket, &object, expire_time, req);
        aos_str_set(&url, url_str);
        printf("臨時下載URL: %s\n", url_str);     
        /* 釋放記憶體池,相當於釋放了請求過程中各資源分派的記憶體。*/
        aos_pool_destroy(pool);
        /* 釋放之前分配的全域資源。*/
        aos_http_io_deinitialize();
        return 0;
    }
  2. 通過簽名URL下載檔案

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