用戶端簽名直傳是指從服務端擷取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快速體驗用戶端簽名直傳的操作步驟如下。
一鍵部署雲資源。
開啟一鍵配置模板連結。
在資源編排 ROS控制台,輸入資源棧名稱,輸入建立OSS Bucket的名稱,設定新購ECS的可用性區域、執行個體類型、系統硬碟類型、執行個體密碼,然後單擊創建。
資源棧的資源棧資訊頁簽下的狀態顯示建立中。
資源棧的狀態顯示建立成功後,單擊輸出頁簽,查看一鍵部署的Elastic Compute Service執行個體、OSS Bucket等資源。
體驗用戶端簽名直傳。
在輸出頁簽下,複製UploadPath的值,然後在瀏覽器中開啟。
在OSS web直傳頁面,單擊選擇檔案,選擇指定類型的檔案,然後單擊開始上傳。
完成與清理
方案驗證
完成以上操作後,您可以查看檔案是否已上傳到OSS。
在左側導覽列,選擇Bucket列表。
在檔案清單頁面,查看成功上傳的檔案。
清理資源
體驗完成後,釋放測試資源,避免繼續產生費用。
資源棧頁面的右上方,單擊刪除。
在刪除資源棧頁面,確保刪除方式為釋放資源,然後單擊確定。
手動部署
準備工作
建立一個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使用者,並擷取對應的存取金鑰,作為商務服務器的應用程式的長期身份憑證。
使用雲帳號或帳號管理員登入RAM控制台。
在左側導覽列,選擇身份管理 > 使用者。
單擊建立使用者。
輸入登入名稱稱和顯示名稱。
在調用方式地區下,選擇OpenAPI調用,然後單擊確定。
單擊操作下的複製,儲存調用密鑰(AccessKey ID和AccessKey Secret)。
步驟二:在存取控制為RAM使用者授予調用AssumeRole介面的許可權
建立RAM使用者後,需要授予RAM使用者調用STS服務的AssumeRole介面的許可權,使其可以通過扮演RAM角色來擷取臨時身份憑證。
在左側導覽列,選擇身份管理 > 使用者。
在使用者頁面,找到目標RAM使用者,然後單擊RAM使用者右側的添加許可權。
在新增授權頁面,選擇AliyunSTSAssumeRoleAccess系統策略。
說明授予RAM使用者調用STS服務AssumeRole介面的固定許可權是AliyunSTSAssumeRoleAccess,與後續擷取臨時訪問憑證以及通過臨時訪問憑證發起OSS請求要求的權限無關。
單擊確認新增授權。
步驟三:在存取控制建立RAM角色
為當前雲帳號建立一個RAM角色,並擷取對應的角色的ARN(Aliyun Resource Name,阿里雲資源名稱),用於RAM使用者之後進行扮演。
在左側導覽列,選擇身份管理 > 角色。
單擊建立角色,可信實體類型選擇阿里雲帳號,單擊下一步。
填寫角色名稱,選擇當前雲帳號。
單擊完成。完成角色建立後,單擊關閉。
在RAM角色管理頁面,搜尋方塊輸入角色名稱,例如
oss-web-upload
。單擊複製,儲存角色的ARN。
步驟四:在存取控制建立自訂權限原則
按照最小授權原則,為RAM角色建立一個自訂權限原則,限制只能向指定OSS的儲存空間進行XX操作。
在左側導覽列,選擇許可權管理 > 權限原則。
單擊建立權限原則。
在建立權限原則頁面,單擊指令碼編輯,將以下指令碼中的
<Bucket名稱>
替換為準備工作中建立的Bucket名稱。重要以下樣本僅供參考。您需要根據實際需求配置更細粒度的授權策略,防止出現許可權過大的風險。關於更細粒度的授權策略配置詳情,請參見Object Storage Service自訂權限原則參考。
{ "Version": "1", "Statement": [ { "Effect": "Allow", "Action": "oss:PutObject", "Resource": "acs:oss:*:*:<Bucket名稱>/uploads/*" } ] }
策略配置完成後,單擊繼續編輯基本資料。
在基本資料地區,填寫策略名稱稱,然後單擊確定。
步驟五:在存取控制為RAM角色授予許可權
為RAM角色授予建立的自訂許可權,以便該RAM角色被扮演時能擷取所需的許可權。
在左側導覽列,選擇身份管理 > 角色。
在角色頁面,找到目標RAM角色,然後單擊RAM角色右側的新增授權。
在新增授權頁面下的自訂策略頁簽,選擇已建立的自訂權限原則。
單擊確定。
步驟六:在商務服務器擷取臨時身份憑證
在Web應用中,通過在商務服務器整合STS SDK,實現一個擷取臨時STS身份憑證的介面。當這個介面(/get_sts_token
)通過HTTP GET方法被訪問時,它會產生一個臨時身份憑證,並將其返回給要求者。
在ECS執行個體上,使用Flask架構快速搭建Web應用,實現一個擷取臨時STS身份憑證的介面的操作樣本如下:
串連ECS執行個體。
具體操作,請參見通過控制台使用ECS執行個體(快捷版)。
安裝Python3。
建立專案檔夾,然後切換到專案目錄。
mkdir my_web_sample cd my_web_sample
安裝依賴。
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
編寫後端代碼。
建立一個
main.py
檔案。在這個檔案中,添加以下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)
將代碼中的
<YOUR_ROLE_ARN>
替換為步驟三擷取的角色ARN。將代碼中的
<YOUR_ROLE_SESSION_NAME>
設定為自訂的會話名稱,例如role_session_test
。
使用步驟一擷取的存取金鑰啟動應用程式。
ALIBABA_CLOUD_ACCESS_KEY_ID=<YOUR_AK_ID> ALIBABA_CLOUD_ACCESS_KEY_SECRET=<YOUR_AK_SECRET> python3 main.py
在瀏覽器中訪問
http://<ECS執行個體公網IP地址>/get_sts_token
。成功返回樣本如下:
按
Ctrl + C
停止應用程式。
步驟七:在瀏覽器使用臨時身份憑證上傳檔案到OSS
在商務服務器配置了擷取STS臨時身份憑證的介面後,在Web應用的前端網頁使用CDN引入OSS JavaScript SDK,實現對檔案上傳的監聽。當使用者上傳檔案,調用/get_sts_token
介面從商務服務器請求臨時訪問憑證,然後使用臨時訪問憑證向OSS上傳檔案。
在ECS上,使用CDN引入方式將OSS JavaScript SDK整合到Web應用的前端代碼的操作樣本如下
按
Ctrl + C
停止應用程式。建立前端專案檔。
mkdir templates
建立HTML模板檔案。
在
templates
目錄中建立一個index.html
檔案。vim templates/index.html
在這個檔案中,添加以下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>
將代碼中的
<YOUR_BUCKET
和<YOUR_REGION>
替換為準備工作中建立的Bucket名稱和Bucket所屬地區ID。關於地區ID,請參見訪問網域名稱和資料中心。
使用步驟一擷取的存取金鑰啟動應用程式。
ALIBABA_CLOUD_ACCESS_KEY_ID=<YOUR_AK_ID> ALIBABA_CLOUD_ACCESS_KEY_SECRET=<YOUR_AK_SECRET> python3 main.py
在瀏覽器中訪問
http://<ECS執行個體公網IP地址>
,然後在頁面中選擇並上傳檔案,類比真實使用者在瀏覽器的行為。
完成與清理
方案驗證
完成以上操作後,您可以查看檔案是否已上傳到OSS。
在左側導覽列,選擇Bucket列表。
在檔案清單頁面,查看成功上傳的檔案。
清理資源
在本方案中,您建立了1台ECS執行個體、1個OSS Bucket、1個RAM使用者和1個RAM角色。測試完方案後,您可以參考以下規則處理對應產品的資源,避免繼續產生費用或產生安全風險。
後續操作
終端使用者在瀏覽器上傳檔案到OSS後:
您可以為檔案產生簽名URL,授權使用者在指定時間內下載或者預覽檔案。具體操作,請參見使用檔案URL分享檔案。
您可以對圖片進行處理,例如添加圖片浮水印、轉換格式等。具體操作,請參見圖片處理。