全部產品
Search
文件中心

Object Storage Service:用戶端簽名直傳

更新時間:Jun 26, 2024

用戶端簽名直傳是指從服務端擷取sts token,並使用sts token產生簽名,最後使用此簽名上傳檔案到OSS。用戶端可以直接將檔案上傳至OSS,減少了中間環節,因此可以加快上傳速度。本文介紹如何進行用戶端簽名直傳。

安全風險

為了減少企業的商務服務器負擔並提高效率,該Web應用被設計為在使用者的網頁瀏覽器中直接與OSS互動,而非所有請求都通過企業的商務服務器中轉。

企業A計劃採取以下方案搭建Web應用檔案直傳服務:

由於網頁瀏覽器運行環境完全處於使用者端且不受企業A直接控制,企業A面臨以下挑戰:

  • 密鑰泄露的重大風險:網頁瀏覽器歸使用者所有,並且被視為不可信的環境。若在瀏覽器中儲存RAM使用者的存取金鑰等敏感資訊,則可能會面臨密鑰意外泄露的顯著風險。一旦密鑰落入不法分子之手,他們就可能利用這些密鑰非法訪問企業在雲端的敏感性資料,導致核心商業機密、客戶隱私資訊、智慧財產權及其他關鍵資產的泄漏,給企業造成不可估量的經濟損失和信譽損害。

  • 過度許可權的安全性漏洞:在為企業的商務服務器應用程式建立RAM使用者時,往往需要賦予該使用者較高的許可權,以便於它可以訪問和管理其他雲端服務。然而,如果使用者的存取金鑰被儲存在瀏覽器中而後又意外泄露,這將可能導致擁有過多許可權的密鑰落入惡意攻擊者之手。此舉不僅增加了企業資源被濫用的機率,還可能帶來更嚴重的問題。駭客可能會使用盜取的密鑰在企業的雲資源上部署病毒或惡意軟體,比如植入後門、植入密碼竊取木馬程式、以企業資源進行加密貨幣挖礦等,嚴重破壞企業的正常業務營運,並對企業的財務和聲譽構成嚴重威脅。

解決方案

為了應對上述風險,企業A可以在原有方案的基礎上增加臨時授權。通過這種方式,企業A能夠在確保資料直傳效率的同時,實現以下效果:

  • 增強身分識別驗證和授權:通過STS產生的具有時間限制的令牌,即便在短時間內泄露,也極大降低了安全風險。因為這些憑證很快就會失效,降低了被不當利用的可能性。

  • 精微調權限控制:STS允許根據最小許可權原則配置許可權,僅授權Web應用必需的存取權限。這種精細化的許可權控制方法限制了潛在泄露的影響範圍,防止了過度許可權的風險。

企業A最終採取以下方案搭建Web應用檔案直傳服務:

方案部署

下面將以一個簡單的使用者檔案上傳情境為例,引導您一步步使用OSS和STS為Web應用部署瀏覽器檔案直傳服務。

本方案部署的樣本工程:oss-upload-sts.zip

一鍵部署

您可以使用Resource Orchestration Service一鍵配置1個Elastic Compute Service執行個體和1個Object Storage Service Bucket,並在Elastic Compute Service執行個體上部署瀏覽器用戶端,從而快速體驗用戶端簽名直傳。使用Resource Orchestration Service快速體驗用戶端簽名直傳的操作步驟如下。

  1. 一鍵部署雲資源。

    1. 開啟一鍵配置模板連結

    2. 資源編排 ROS控制台,輸入資源棧名稱,輸入建立OSS Bucket的名稱,設定新購ECS的可用性區域、執行個體類型、系統硬碟類型、執行個體密碼,然後單擊創建

      資源棧的資源棧資訊頁簽下的狀態顯示建立中

    3. 資源棧的狀態顯示建立成功後,單擊輸出頁簽,查看一鍵部署的Elastic Compute Service執行個體、OSS Bucket等資源。

  2. 體驗用戶端簽名直傳。

    1. 輸出頁簽下,複製UploadPath的值,然後在瀏覽器中開啟。

    2. OSS web直傳頁面,單擊選擇檔案,選擇指定類型的檔案,然後單擊開始上傳

完成與清理

方案驗證

完成以上操作後,您可以查看檔案是否已上傳到OSS。

  1. 登入Object Storage Service控制台

  2. 在左側導覽列,選擇Bucket列表

  3. Bucket列表頁面,單擊目標Bucket。

  4. 檔案清單頁面,查看成功上傳的檔案。

    1.png

清理資源

體驗完成後,釋放測試資源,避免繼續產生費用。

  1. 資源棧頁面的右上方,單擊刪除

  2. 刪除資源棧頁面,確保刪除方式釋放資源,然後單擊確定

手動部署

準備工作

  • 建立一個OSS Bucket,用於儲存Web應用在瀏覽器環境中直接上傳的檔案。

    參數

    樣本值

    所屬地區

    華東1(杭州)

    Bucket名稱

    web-direct-upload

    具體步驟,請參見建立儲存空間

  • 建立一台ECS執行個體作為商務服務器,用於產生臨時身份憑證。

    說明

    在實際部署時,您可以將調用STS服務的介面整合到自己的商務服務器的介面中,而無需建立該ECS執行個體。

    參數

    樣本值

    付費類型

    隨用隨付

    地區

    華東1(杭州)

    公網 IP

    分配公網 IPv4 地址

    安全性群組

    開放HTTP (TCP:80)連接埠

    具體步驟,請參見通過控制台使用ECS執行個體(快捷版)

  • 為建立的OSS Bucket配置跨域資源共用。

    參數

    樣本值

    來源

    http://ECS公網IP地址

    允許Methods

    PUT

    允許Headers

    *

    具體步驟,請參見跨網域設定

部署步驟

步驟一:在存取控制建立RAM使用者

首先,建立一個調用方式為OpenAPI調用的RAM使用者,並擷取對應的存取金鑰,作為商務服務器的應用程式的長期身份憑證。

  1. 使用雲帳號或帳號管理員登入RAM控制台

  2. 在左側導覽列,選擇身份管理 > 使用者

  3. 單擊建立使用者

  4. 輸入登入名稱稱顯示名稱

  5. 調用方式地區下,選擇OpenAPI調用,然後單擊確定

  6. 單擊操作下的複製,儲存調用密鑰(AccessKey ID和AccessKey Secret)。

步驟二:在存取控制為RAM使用者授予調用AssumeRole介面的許可權

建立RAM使用者後,需要授予RAM使用者調用STS服務的AssumeRole介面的許可權,使其可以通過扮演RAM角色來擷取臨時身份憑證。

  1. 在左側導覽列,選擇身份管理 > 使用者

  2. 使用者頁面,找到目標RAM使用者,然後單擊RAM使用者右側的添加許可權

  3. 新增授權頁面,選擇AliyunSTSAssumeRoleAccess系統策略。

    說明

    授予RAM使用者調用STS服務AssumeRole介面的固定許可權是AliyunSTSAssumeRoleAccess,與後續擷取臨時訪問憑證以及通過臨時訪問憑證發起OSS請求要求的權限無關。

  4. 單擊確認新增授權

步驟三:在存取控制建立RAM角色

為當前雲帳號建立一個RAM角色,並擷取對應的角色的ARN(Aliyun Resource Name,阿里雲資源名稱),用於RAM使用者之後進行扮演。

  1. 在左側導覽列,選擇身份管理 > 角色

  2. 單擊建立角色,可信實體類型選擇阿里雲帳號,單擊下一步

  3. 填寫角色名稱,選擇當前雲帳號

  4. 單擊完成。完成角色建立後,單擊關閉

  5. 在RAM角色管理頁面,搜尋方塊輸入角色名稱,例如oss-web-upload

  6. 單擊複製,儲存角色的ARN。

    1.png

步驟四:在存取控制建立自訂權限原則

按照最小授權原則,為RAM角色建立一個自訂權限原則,限制只能向指定OSS的儲存空間進行XX操作。

  1. 在左側導覽列,選擇許可權管理 > 權限原則

  2. 單擊建立權限原則

  3. 建立權限原則頁面,單擊指令碼編輯,將以下指令碼中的<Bucket名稱>替換為準備工作中建立的Bucket名稱。

    重要

    以下樣本僅供參考。您需要根據實際需求配置更細粒度的授權策略,防止出現許可權過大的風險。關於更細粒度的授權策略配置詳情,請參見Object Storage Service自訂權限原則參考

    {
      "Version": "1",
      "Statement": [
        {
          "Effect": "Allow",
          "Action": "oss:PutObject",
          "Resource": "acs:oss:*:*:<Bucket名稱>/uploads/*"
        }
      ]
    }
  4. 策略配置完成後,單擊繼續編輯基本資料

  5. 基本資料地區,填寫策略名稱稱,然後單擊確定

步驟五:在存取控制為RAM角色授予許可權

為RAM角色授予建立的自訂許可權,以便該RAM角色被扮演時能擷取所需的許可權。

  1. 在左側導覽列,選擇身份管理 > 角色

  2. 角色頁面,找到目標RAM角色,然後單擊RAM角色右側的新增授權

  3. 新增授權頁面下的自訂策略頁簽,選擇已建立的自訂權限原則。

  4. 單擊確定

步驟六:在商務服務器擷取臨時身份憑證

在Web應用中,通過在商務服務器整合STS SDK,實現一個擷取臨時STS身份憑證的介面。當這個介面(/get_sts_token)通過HTTP GET方法被訪問時,它會產生一個臨時身份憑證,並將其返回給要求者。

在ECS執行個體上,使用Flask架構快速搭建Web應用,實現一個擷取臨時STS身份憑證的介面的操作樣本如下:

  1. 串連ECS執行個體。

    具體操作,請參見通過控制台使用ECS執行個體(快捷版)

  2. 安裝Python3

  3. 建立專案檔夾,然後切換到專案目錄。

    mkdir my_web_sample
    cd my_web_sample
  4. 安裝依賴。

    pip3 install Flask
    pip3 install attr
    pip3 install yarl
    pip3 install async_timeout
    pip3 install idna_ssl
    pip3 install attrs
    pip3 install aiosignal
    pip3 install charset_normalizer
    pip3 install alibabacloud_tea_openapi
    pip3 install alibabacloud_sts20150401
    pip3 install alibabacloud_credentials
  5. 編寫後端代碼。

    1. 建立一個main.py檔案。

    2. 在這個檔案中,添加以下Python代碼。

      import json
      from flask import Flask, render_template
      from alibabacloud_tea_openapi.models import Config
      from alibabacloud_sts20150401.client import Client as Sts20150401Client
      from alibabacloud_sts20150401 import models as sts_20150401_models
      from alibabacloud_credentials.client import Client as CredentialClient
      
      app = Flask(__name__)
      
      # 將<YOUR_ROLE_ARN>替換為RAM角色的ARN。
      role_arn_for_oss_upload = '<YOUR_ROLE_ARN>'
      # 設定為STS服務的地區,例如cn-hangzhou。
      region_id = 'cn-hangzhou'
      
      @app.route("/")
      def hello_world():
          return render_template('index.html')
      
      @app.route('/get_sts_token', methods=['GET'])
      def get_sts_token():
          # 初始化 CredentialClient 時不指定參數,代表使用預設憑據鏈。
          # 在本地運行程式時,可以通過環境變數 ALIBABA_CLOUD_ACCESS_KEY_ID、ALIBABA_CLOUD_ACCESS_KEY_SECRET 指定 AK;
          # 在 ECS\ECI\Container Service上運行時,可以通過環境變數 ALIBABA_CLOUD_ECS_METADATA 來指定綁定的執行個體節點角色,SDK 會自動換取 STS 臨時憑證。
          config = Config(region_id=region_id, credential=CredentialClient())
          sts_client = Sts20150401Client(config=config)
          assume_role_request = sts_20150401_models.AssumeRoleRequest(
              role_arn=role_arn_for_oss_upload,
              # 將<YOUR_ROLE_SESSION_NAME>設定為自訂的會話名稱。
              role_session_name='<YOUR_ROLE_SESSION_NAME>'
          )
          response = sts_client.assume_role(assume_role_request)
          token = json.dumps(response.body.credentials.to_map())
          return token
      
      app.run(host="0.0.0.0", port=80)
    3. 將代碼中的<YOUR_ROLE_ARN>替換為步驟三擷取的角色ARN。

    4. 將代碼中的<YOUR_ROLE_SESSION_NAME>設定為自訂的會話名稱,例如role_session_test

  6. 使用步驟一擷取的存取金鑰啟動應用程式。

    ALIBABA_CLOUD_ACCESS_KEY_ID=<YOUR_AK_ID> ALIBABA_CLOUD_ACCESS_KEY_SECRET=<YOUR_AK_SECRET> python3 main.py
  7. 在瀏覽器中訪問http://<ECS執行個體公網IP地址>/get_sts_token

    成功返回樣本如下:

    sts token.png

  8. Ctrl + C停止應用程式。

步驟七:在瀏覽器使用臨時身份憑證上傳檔案到OSS

在商務服務器配置了擷取STS臨時身份憑證的介面後,在Web應用的前端網頁使用CDN引入OSS JavaScript SDK,實現對檔案上傳的監聽。當使用者上傳檔案,調用/get_sts_token介面從商務服務器請求臨時訪問憑證,然後使用臨時訪問憑證向OSS上傳檔案。

在ECS上,使用CDN引入方式將OSS JavaScript SDK整合到Web應用的前端代碼的操作樣本如下

  1. Ctrl + C停止應用程式。

  2. 建立前端專案檔。

    mkdir templates
  3. 建立HTML模板檔案。

    1. templates目錄中建立一個index.html檔案。

      vim templates/index.html
    2. 在這個檔案中,添加以下HTML代碼。

      <!DOCTYPE html>
      <html lang="zh-CN">
        <head>
          <meta charset="UTF-8" />
          <meta name="viewport" content="width=device-width, initial-scale=1.0" />
          <title>上傳檔案到OSS</title>
          <script src="https://gosspublic.alicdn.com/aliyun-oss-sdk-6.17.0.min.js"></script>
        </head>
        <body>
          <div class="container">
            <form>
              <div class="mb-3">
                <label for="file" class="form-label">選擇檔案</label>
                <input
                  type="file"
                  class="form-control"
                  id="file"
                  name="file"
                  required
                />
              </div>
              <button type="submit" class="btn btn-primary">上傳</button>
            </form>
          </div>
          <script type="text/javascript">
            let credentials = null;
            const form = document.querySelector("form");
            form.addEventListener("submit", async (event) => {
              event.preventDefault();
              // 臨時憑證到期時,才重新擷取,減少對 sts 服務的調用
              if (isCredentialsExpired(credentials)) {
                const response = await fetch("/get_sts_token", {
                  method: "GET",
                });
                if (!response.ok) {
                  // 處理錯誤的HTTP狀態代碼
                  throw new Error(
                    `擷取STS令牌失敗: ${response.status} ${response.statusText}`
                  );
                }
                credentials = await response.json();
              }
              const client = new OSS({
                // 將<YOUR_BUCKET>設定為OSS Bucket名稱。
                bucket: "<YOUR_BUCKET>",
                // 將<YOUR_REGION>設定為OSS Bucket所在地區,例如oss-cn-hangzhou。
                region: "<YOUR_REGION>",
                accessKeyId: credentials.AccessKeyId,
                accessKeySecret: credentials.AccessKeySecret,
                stsToken: credentials.SecurityToken,
              });
      
              const fileInput = document.querySelector("#file");
              const file = fileInput.files[0];
              const result = await client.put('uploads/'+file.name, file);
              console.log(result);
            });
      
            /**
             * 判斷臨時憑證是否到期。
             **/
            function isCredentialsExpired(credentials) {
              if (!credentials) {
                return true;
              }
              const expireDate = new Date(credentials.Expiration);
              const now = new Date();
              // 如果有效期間不足一分鐘,視為到期。
              return expireDate.getTime() - now.getTime() <= 60000;
            }
          </script>
        </body>
      </html>
    3. 將代碼中的<YOUR_BUCKET<YOUR_REGION>替換為準備工作中建立的Bucket名稱和Bucket所屬地區ID。關於地區ID,請參見訪問網域名稱和資料中心

  4. 使用步驟一擷取的存取金鑰啟動應用程式。

    ALIBABA_CLOUD_ACCESS_KEY_ID=<YOUR_AK_ID> ALIBABA_CLOUD_ACCESS_KEY_SECRET=<YOUR_AK_SECRET> python3 main.py
  5. 在瀏覽器中訪問http://<ECS執行個體公網IP地址>,然後在頁面中選擇並上傳檔案,類比真實使用者在瀏覽器的行為。

    2024-05-10_11-10-45.png

完成與清理

方案驗證

完成以上操作後,您可以查看檔案是否已上傳到OSS。

  1. 登入Object Storage Service控制台

  2. 在左側導覽列,選擇Bucket列表

  3. Bucket列表頁面,單擊目標Bucket。

  4. 檔案清單頁面,查看成功上傳的檔案。

    1.png

清理資源

在本方案中,您建立了1台ECS執行個體、1個OSS Bucket、1個RAM使用者和1個RAM角色。測試完方案後,您可以參考以下規則處理對應產品的資源,避免繼續產生費用或產生安全風險。

後續操作

終端使用者在瀏覽器上傳檔案到OSS後:

  • 您可以為檔案產生簽名URL,授權使用者在指定時間內下載或者預覽檔案。具體操作,請參見使用檔案URL分享檔案

  • 您可以對圖片進行處理,例如添加圖片浮水印、轉換格式等。具體操作,請參見圖片處理

常見問題

上傳後如何擷取檔案URL?

您可以根據Bucket訪問網域名稱及檔案訪問路徑擷取檔案的URL,詳情請參見使用檔案URL分享檔案