本文中含有需要您注意的重要提示信息,忽略該信息可能對您的業務造成影響,請務必仔細閱讀。
本文介紹如何使用STS以及簽名URL臨時授權訪問OSS資源。
由于STS臨時賬號以及簽名URL均需設置有效時長,當您使用STS臨時賬號生成簽名URL執行相關操作(例如上傳、下載文件)時,以最小的有效時長為準。例如您的STS臨時賬號的有效時長設置為1200秒、簽名URL設置為3600秒時,當有效時長超過1200秒后,您無法使用此STS臨時賬號生成的簽名URL上傳文件。
使用STS進行臨時授權
OSS可以通過阿里云STS(Security Token Service)進行臨時授權訪問。阿里云STS是為云計算用戶提供臨時訪問令牌的Web服務。通過STS,您可以為第三方應用或子用戶(即用戶身份由您自己管理的用戶)頒發一個自定義時效和權限的訪問憑證。關于STS的更多信息,請參見STS介紹。
STS的優勢如下:
您無需透露您的長期密鑰(AccessKey)給第三方應用,只需生成一個訪問令牌并將令牌交給第三方應用。您可以自定義這個令牌的訪問權限及有效期限。
您無需關心權限撤銷問題,訪問令牌過期后自動失效。
通過STS臨時授權訪問OSS的步驟如下:
登錄RAM控制臺。
在左側導航欄,選擇身份管理>用戶。
單擊創建用戶。
輸入登錄名稱和顯示名稱。
在訪問方式區域下,選擇OpenAPI調用訪問,然后單擊確定。
根據界面提示,完成安全驗證。
復制訪問密鑰(AccessKey ID和AccessKey Secret)。
重要RAM用戶的AccessKey Secret只在創建時顯示,后續不支持查看,請妥善保管。
單擊已創建RAM用戶右側對應的添加權限。
在新增授權頁面,選擇AliyunSTSAssumeRoleAccess系統策略。
說明授予RAM用戶調用STS服務AssumeRole接口的固定權限是AliyunSTSAssumeRoleAccess,與后續獲取臨時訪問憑證以及通過臨時訪問憑證發起OSS請求所需權限無關。
單擊確認新增授權。
在左側導航欄,選擇身份管理>角色。
單擊創建角色,選擇可信實體類型為阿里云賬號,單擊下一步。
在創建角色對話框,角色名稱填寫為RamOssTest,選擇信任的云賬號為當前云賬號。
單擊完成。角色創建完成后,單擊關閉。
在角色頁面,搜索框輸入角色名稱RamOssTest,然后單擊RamOssTest。
單擊ARN右側的復制,保存角色的ARN。
為角色授予上傳文件和下載文件的自定義權限策略。
在左側導航欄,選擇權限管理>權限策略。
在權限策略頁面,單擊創建權限策略。
在創建權限策略頁面,單擊腳本編輯,然后在策略文檔輸入框中賦予角色向目標存儲空間examplebucket執行簡單上傳(oss:PutObject)和下載文件(oss:GetObject)的權限。具體配置示例如下。
警告以下示例僅供參考。您需要根據實際需求配置更細粒度的授權策略,防止出現權限過大的風險。關于更細粒度的授權策略配置詳情,請參見通過RAM或STS服務向其他用戶授權。
{ "Version": "1", "Statement": [ { "Effect": "Allow", "Action": [ "oss:PutObject", "oss:GetObject" ], "Resource": [ "acs:oss:*:*:examplebucket", "acs:oss:*:*:examplebucket/*" ] } ] }
策略配置完成后,單擊繼續編輯基本信息。
在基本信息區域,填寫策略名稱為RamTestPolicy,然后單擊確定。
為RAM角色RamOssTest授予自定義權限策略。
在左側導航欄,選擇
。在角色頁面,找到目標RAM角色RamOssTest。
單擊RAM角色RamOssTest右側的新增授權。
在添加權限頁面下的自定義策略頁簽,選擇已創建的自定義權限策略RamTestPolicy。
單擊確定。
臨時訪問憑證包括臨時訪問密鑰(AccessKey ID和AccessKey Secret)和安全令牌(SecurityToken)。臨時訪問憑證有效時間單位為秒,最小值為900,最大值以當前角色設定的最大會話時間為準。更多信息,請參見設置RAM角色最大會話時間。
使用express模塊前,請確保已安裝express模塊。如果未安裝,請執行npm install express --save命令進行安裝。
const { STS } = require('ali-oss');
const express = require("express");
const app = express();
app.get('/sts', (req, res) => {
let sts = new STS({
// 填寫步驟1創建的RAM用戶AccessKey。
accessKeyId: 'yourAccessKeyId',
accessKeySecret: 'yourAccessKeySecret'
});
// roleArn填寫步驟2獲取的角色ARN,例如acs:ram::175708322470****:role/ramtest。
// policy填寫自定義權限策略,用于進一步限制STS臨時訪問憑證的權限。如果不指定Policy,則返回的STS臨時訪問憑證默認擁有指定角色的所有權限。
// 臨時訪問憑證最后獲得的權限是步驟4設置的角色權限和該Policy設置權限的交集。
// expiration用于設置臨時訪問憑證有效時間單位為秒,最小值為900,最大值以當前角色設定的最大會話時間為準。本示例指定有效時間為3000秒。
// sessionName用于自定義角色會話名稱,用來區分不同的令牌,例如填寫為sessiontest。
sts.assumeRole('acs:ram::175708322470****:role/ramtest', ``, '3000', 'sessiontest').then((result) => {
console.log(result);
res.set('Access-Control-Allow-Origin', '*');
res.set('Access-Control-Allow-METHOD', 'GET');
res.json({
AccessKeyId: result.credentials.AccessKeyId,
AccessKeySecret: result.credentials.AccessKeySecret,
SecurityToken: result.credentials.SecurityToken,
Expiration: result.credentials.Expiration
});
}).catch((err) => {
console.log(err);
res.status(400).json(err.message);
});
});
app.listen(8000,()=>{
console.log("server listen on:8000")
})
使用臨時訪問憑證上傳文件
說明此步驟中的示例需要依賴axios,請在運行前下載
const axios = require("axios"); const OSS = require("ali-oss"); // 在客戶端使用臨時訪問憑證初始化OSS客戶端,用于臨時授權訪問OSS資源。 const getToken = async () => { // 設置客戶端請求訪問憑證的地址。 await axios.get("http://localhost:8000/sts").then((token) => { const client = new OSS({ // yourRegion填寫Bucket所在地域。以華東1(杭州)為例,yourRegion填寫為oss-cn-hangzhou。 region: 'oss-cn-hangzhou', accessKeyId: token.data.AccessKeyId, accessKeySecret: token.data.AccessKeySecret, stsToken: token.data.SecurityToken, authorizationV4: true, // 填寫Bucket名稱。 bucket: "examplebucket", // 刷新臨時訪問憑證。 refreshSTSToken: async () => { const refreshToken = await axios.get("http://localhost:8000/sts"); return { accessKeyId: refreshToken.AccessKeyId, accessKeySecret: refreshToken.AccessKeySecret, stsToken: refreshToken.SecurityToken, }; }, }); // 使用臨時訪問憑證上傳文件。 // 填寫不包含Bucket名稱在內的Object的完整路徑,例如exampleobject.jpg。 // 填寫本地文件的完整路徑,例如D:\\example.jpg。 client.put('exampleobject.jpg', 'D:\\example.jpg').then((res)=>{console.log(res)}).catch(e=>console.log(e)) }); }; getToken()
使用臨時訪問憑證下載文件
const axios = require("axios"); const OSS = require("ali-oss"); // 在客戶端使用臨時訪問憑證初始化OSS客戶端,用于臨時授權訪問OSS資源。 const getToken = async () => { // 設置客戶端請求訪問憑證的地址。 await axios.get("http://localhost:8000/sts").then((token) => { const client = new OSS({ // yourRegion填寫Bucket所在地域。以華東1(杭州)為例,yourRegion填寫為oss-cn-hangzhou。 region: 'oss-cn-hangzhou', accessKeyId: token.data.AccessKeyId, accessKeySecret: token.data.AccessKeySecret, stsToken: token.data.SecurityToken, authorizationV4: true, // 填寫Bucket名稱。 bucket: "examplebucket", // 刷新臨時訪問憑證。 refreshSTSToken: async () => { const refreshToken = await axios.get("http://localhost:8000/sts"); return { accessKeyId: refreshToken.AccessKeyId, accessKeySecret: refreshToken.AccessKeySecret, stsToken: refreshToken.SecurityToken, }; }, }); // 使用臨時訪問憑證下載文件。 // 填寫不包含Bucket名稱在內的Object的完整路徑,例如exampleobject.jpg。 // 填寫本地文件的完整路徑,例如D:\\example.jpg。 client.get('exampleobject.jpg', 'D:\\example.jpg').then((res)=>{console.log(res)}).catch(e=>console.log(e)) }); }; getToken()
使用簽名URL進行臨時授權
注意事項
生成簽名URL過程中,SDK利用本地存儲的密鑰信息,根據特定算法計算出簽名(signature),然后將其附加到URL上,以確保URL的有效性和安全性。這一系列計算和構造URL的操作都是在客戶端完成,不涉及網絡請求到服務端。因此,生成簽名URL時不需要授予調用者特定權限。但是,為避免第三方用戶無法對簽名URL授權的資源執行相關操作,需要確保調用生成簽名URL接口的身份主體被授予對應的權限。
例如,通過簽名URL上傳文件時,需要授予oss:PutObject權限。通過簽名URL下載或預覽文件時,需要授予oss:GetObject權限。
您可以將生成的簽名URL提供給訪客進行臨時訪問。生成簽名URL時,您可以自定義URL的過期時間來限制訪客的訪問時長。
通過以下示例生成的簽名URL中如果包含特殊符號
+
,可能出現無法正常訪問該簽名URL的現象。如需正常訪問該簽名URL,請將簽名URL中的+
替換為%2B
。
生成帶圖片處理參數的簽名URL
const OSS = require('ali-oss');
const store = new OSS({
// yourRegion填寫Bucket所在地域。以華東1(杭州)為例,yourRegion填寫為oss-cn-hangzhou。
region: 'yourRegion',
// 從環境變量中獲取訪問憑證。運行本代碼示例之前,請確保已設置環境變量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
accessKeyId: process.env.OSS_ACCESS_KEY_ID,
accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET,
// 填寫Bucket名稱。
bucket: 'examplebucket'
})
// 獲取處理exampleobject.png圖片的簽名URL。
// 填寫不包含Bucket名稱在內的Object完整路徑。
let url = store.signatureUrl('exampleobject.png', {
process: 'image/resize,w_200' // 設置圖片處理參數。
});
console.log(url);
// 獲取處理exampleobject.png圖片的簽名URL,并設置過期時間。
// 填寫不包含Bucket名稱在內的Object完整路徑。
let url = store.signatureUrl('exampleobject.png', {
// 設置過期時間,默認值為1800秒。
expires: 3600,
// 設置圖片處理參數。
process: 'image/resize,w_200'
});
console.log(url);
生成帶versionId的簽名URL
const OSS = require('ali-oss');
const client = new OSS({
// yourRegion填寫Bucket所在地域。以華東1(杭州)為例,yourRegion填寫為oss-cn-hangzhou。
region: 'yourRegion',
// 從環境變量中獲取訪問憑證。運行本代碼示例之前,請確保已設置環境變量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
accessKeyId: process.env.OSS_ACCESS_KEY_ID,
accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET,
// 填寫Bucket名稱。
bucket: 'examplebucket'
})
// 生成帶versionId的簽名URL。
// 填寫不包含Bucket名稱在內的Object完整路徑,例如example.png。
console.log(
client.signatureUrl('example.jpg', {
subResource: {
// 填寫Object的versionId。
versionId: 'CAEQMBiBgIDW7duIqxgiIDA4OWRiYmFlZDUxMDQ3YzM4OWUyNjQzMzAzMDhj****',
},
})
)
生成簽名URL并通過簽名URL上傳文件
const OSS = require("ali-oss");
const { default: axios } = require("axios");
const fs = require("fs");
const client = new OSS({
// yourregion填寫Bucket所在地域。以華東1(杭州)為例,Region填寫為oss-cn-hangzhou。
region: 'yourregion',
// 從環境變量中獲取訪問憑證。運行本代碼示例之前,請確保已設置環境變量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
accessKeyId: process.env.OSS_ACCESS_KEY_ID,
accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET,
authorizationV4: true,
// 填寫Bucket名稱。
bucket: 'examplebucket',
});
// 生成文件的簽名URL。
const url = client.signatureUrl("examplefile.txt", {
method: "PUT",
"Content-Type": "application/x-www-form-urlencoded",
});
// 指定本地文件的完整路徑。
const file = fs.readFileSync("D:\\localpath\\examplefile.txt");
// 使用簽名URL上傳文件。
axios({
url,
method: "PUT",
data: file,
})
.then((r) => console.log(r))
.catch((e) => console.log(e));
生成簽名URL并通過簽名URL下載文件
const { default: axios } = require("axios");
const fs = require("fs");
const client = new OSS({
// yourRegion填寫Bucket所在地域。以華東1(杭州)為例,yourRegion填寫為oss-cn-hangzhou。
region: 'yourRegion',
// 從環境變量中獲取訪問憑證。運行本代碼示例之前,請確保已設置環境變量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
accessKeyId: process.env.OSS_ACCESS_KEY_ID,
accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET,
authorizationV4: true,
// 填寫Bucket名稱。
bucket: 'examplebucket'
});
// 生成文件的簽名URL。
const url = client.signatureUrl("examplefile.txt");
// 通過簽名URL下載文件到本地,并填寫下載到本地的文件完整路徑。
const file = "D:\\localpath\\examplefile.txt";
axios({
url,
method: "GET",
})
.then((r) => {
fs.writeFile(file, r.data, (err) => {
if (err) {
console.log(err);
}
});
})
.catch((e) => console.log(e));
常見問題
生成簽名URL時是否支持使用POST方法?
不支持。生成簽名URL時僅支持使用PUT和GET方法。如果您需要通過POST方法進行上傳,您需要參考PostObject自行構造POST請求。