全部產品
Search
文件中心

Object Storage Service:使用STS臨時訪問憑證訪問OSS

更新時間:Mar 13, 2025

通過STS服務,您可以為使用者產生臨時訪問憑證,使其在有效期間內訪問受策略限制的OSS資源。超過有效期間後,憑證自動失效,無法繼續訪問OSS資源,確保了存取控制的靈活性和時效性。

使用情境

某電商企業A把海量商品資料存放在阿里雲OSS中。供應商企業B需要定期向A的OSS上傳資料,並通過自己的系統與企業A的阿里雲資源對接。

對於資訊安全方面,企業A有如下需求:

  • 資料安全:企業A不希望將固定存取金鑰(AccessKey)泄露給企業B,以免核心資料被非法擷取和濫用。

  • 許可權控制:企業A希望暫時僅賦予企業B上傳許可權,後續再根據需求對許可權進行動態調整,以實現對許可權的精準控制。

  • 許可權管理:面對企業B以及後續的其他夥伴,企業A希望能夠靈活地為每個夥伴或臨時需求產生相應的憑證,而無需不斷管理和配置固定的存取金鑰(AccessKey)許可權。

  • 限時存取控制:企業A希望根據企業B的具體需求,限制其對資料訪問的有效時間。到期後,企業B將自動失去存取權限,從而實現對資料互動時效性的嚴格控制。

方案概覽

企業A通過臨時訪問憑證授權企業B安全地將檔案上傳到OSS。

企業A需首先建立RAM使用者和RAM角色,並完成相關授權操作。之後,企業B向企業A申請臨時訪問憑證,企業A調用AssumeRole介面擷取STS臨時訪問憑證,然後將其傳遞給企業B。企業B拿到該憑證後,即可將資料上傳至企業A的OSS中。

前提條件

企業A已建立Bucket。具體操作,請參見建立儲存空間

步驟一:企業A頒發臨時訪問憑證

1. 建立RAM使用者

使用阿里雲主帳號或擁有存取控制(RAM)系統管理權限的RAM帳號建立RAM使用者

  1. 登入RAM控制台

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

  3. 單擊创建用户

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

  5. 访问方式地區下,選擇使用永久 AccessKey 訪問,然後單擊確定

  6. 根據介面提示,完成安全驗證。

  7. 複製存取金鑰(AccessKey ID和AccessKey Secret)。

    重要

    RAM使用者的AccessKey Secret只在建立時顯示,後續不支援查看,請妥善保管。

2. 為RAM使用者授予請求AssumeRole的許可權

建立完RAM使用者後,使用阿里雲主帳號或擁有存取控制(RAM)系統管理權限的RAM帳號授予該RAM使用者通過扮演角色調用STS服務的許可權。

  1. 單擊已建立RAM使用者右側對應的添加权限

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

    說明

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

    image.png

  3. 單擊確認新增授權

3. 建立RAM角色

使用阿里雲主帳號或擁有存取控制(RAM)系統管理權限的RAM帳號建立RAM角色用於定義RAM角色被扮演時,可以獲得OSS服務的哪些存取權限。

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

  2. 單擊创建角色,選擇可信實體類型為阿里云账号,單擊下一步

  3. 创建角色對話方塊,角色名称填寫為RamOssTest,选择信任的云账号当前云账号

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

  5. 角色頁面,搜尋方塊輸入角色名稱RamOssTest,然後單擊RamOssTest

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

4. 為RAM角色授予上傳檔案的許可權

建立完RAM角色後,使用阿里雲主帳號或擁有存取控制(RAM)系統管理權限的RAM帳號為RAM角色附加一個或多個權限原則,明確RAM角色在被扮演時所能擁有的OSS資源存取權限。例如,如果希望RAM使用者在扮演該角色後只能向OSS指定Bucket上傳檔案,則需要為角色添加寫入許可權的策略。

  1. 建立上傳檔案的自訂權限原則。

    1. 在左側導覽列,選擇权限管理>权限策略

    2. 权限策略頁面,單擊创建权限策略

    3. 创建权限策略頁面,單擊指令碼編輯,然後在策略文檔輸入框中賦予角色上傳檔案到examplebucket的許可權。具體配置樣本如下。

      警告

      以下樣本僅供參考。您需要根據實際需求配置更細粒度的授權策略,防止出現許可權過大的風險。關於更細粒度的授權策略配置詳情,請參見通過RAM或STS服務向其他使用者授權

      {
          "Version": "1",
          "Statement": [
           {
                 "Effect": "Allow",
                 "Action": [
                   "oss:PutObject"
                 ],
                 "Resource": [
                   "acs:oss:*:*:examplebucket/*"             
                 ]
           }
          ]
      }
      說明

      RAM角色所擁有的OSS許可權取決於Action的配置,例如授予oss:PutObject許可權,則RAM使用者在扮演RAM角色時可以對指定Bucket執行簡單上傳、表單上傳、追加上傳、分區上傳、斷點續傳上傳等操作。更多資訊,請參見OSS Action說明

    4. 策略配置完成後,單擊繼續編輯基本資料

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

  2. 為RAM角色RamOssTest授予自訂權限原則。

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

    2. 角色頁面,找到目標RAM角色RamOssTest

    3. 單擊RAM角色RamOssTest右側的新增授權

    4. 添加許可權頁面下的自訂策略頁簽,選擇已建立的自訂權限原則RamTestPolicy

    5. 單擊確定

5. 使用RAM使用者扮演RAM角色擷取臨時訪問憑證

重要

STS臨時訪問憑證無法通過阿里雲主帳號的存取金鑰(AccessKey)調用STS API介面擷取,否則會導致報錯失敗。以下樣本將以使用RAM使用者的存取金鑰(AccessKey)為例進行操作。

  • 為角色授予上傳檔案的許可權後,RAM使用者需要通過扮演角色來擷取臨時訪問憑證。臨時訪問憑證包括安全性權杖(SecurityToken)、臨時存取金鑰(AccessKeyId和AccessKeySecret)以及到期時間(Expiration)。您可以使用STS SDK擷取具有簡單上傳(oss:PutObject)許可權的臨時訪問憑證。有關更多語言的STS SDK樣本,請參見STS SDK概覽

  • 範例程式碼中的endpoint為STS服務存取點地址。為了獲得更快的STS服務響應速度,您可以根據伺服器所處地區,選擇對應的或相近的STS服務存取點地址進行填寫。有關STS服務存取點地址資訊,請參見服務存取點

Java

import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import com.aliyuncs.auth.sts.AssumeRoleRequest;
import com.aliyuncs.auth.sts.AssumeRoleResponse;
public class StsServiceSample {
    public static void main(String[] args) { 
        // STS服務存取點,例如sts.cn-hangzhou.aliyuncs.com。您可以通過公網或者VPC接入STS服務。       
        String endpoint = "sts.cn-hangzhou.aliyuncs.com";
        // 從環境變數中擷取步驟1.1產生的RAM使用者的存取金鑰(AccessKey ID和AccessKey Secret)。
        String accessKeyId = System.getenv("ACCESS_KEY_ID");
        String accessKeySecret = System.getenv("ACCESS_KEY_SECRET");
        // 從環境變數中擷取步驟1.3產生的RAM角色的RamRoleArn。
        String roleArn = System.getenv("RAM_ROLE_ARN");
        // 自訂角色會話名稱,用來區分不同的令牌,例如可填寫為SessionTest。        
        String roleSessionName = "yourRoleSessionName";   
        // 臨時訪問憑證將獲得角色擁有的所有許可權。      
        String policy = null;
        // 臨時訪問憑證的有效時間,單位為秒。最小值為900,最大值以當前角色設定的最大會話時間為準。當前角色最大會話時間取值範圍為3600秒~43200秒,預設值為3600秒。
        // 在上傳大檔案或者其他較耗時的使用情境中,建議合理設定臨時訪問憑證的有效時間,確保在完成目標任務前無需反覆調用STS服務以擷取臨時訪問憑證。
        Long durationSeconds = 3600L;
        try {
            // 發起STS請求所在的地區。建議保留預設值,預設值為空白字串("")。
            String regionId = "";
            // 添加endpoint。適用於Java SDK 3.12.0及以上版本。
            DefaultProfile.addEndpoint(regionId, "Sts", endpoint);
            // 添加endpoint。適用於Java SDK 3.12.0以下版本。
            // DefaultProfile.addEndpoint("",regionId, "Sts", endpoint);
            // 構造default profile。
            IClientProfile profile = DefaultProfile.getProfile(regionId, accessKeyId, accessKeySecret);
            // 構造client。
            DefaultAcsClient client = new DefaultAcsClient(profile);
            final AssumeRoleRequest request = new AssumeRoleRequest();
            // 適用於Java SDK 3.12.0及以上版本。
            request.setSysMethod(MethodType.POST);
            // 適用於Java SDK 3.12.0以下版本。
            // request.setMethod(MethodType.POST);
            request.setRoleArn(roleArn);
            request.setRoleSessionName(roleSessionName);
            request.setPolicy(policy); 
            request.setDurationSeconds(durationSeconds); 
            final AssumeRoleResponse response = client.getAcsResponse(request);
            System.out.println("Expiration: " + response.getCredentials().getExpiration());
            System.out.println("Access Key Id: " + response.getCredentials().getAccessKeyId());
            System.out.println("Access Key Secret: " + response.getCredentials().getAccessKeySecret());
            System.out.println("Security Token: " + response.getCredentials().getSecurityToken());
            System.out.println("RequestId: " + response.getRequestId());
        } catch (ClientException e) {
            System.out.println("Failed:");
            System.out.println("Error code: " + e.getErrCode());
            System.out.println("Error message: " + e.getErrMsg());
            System.out.println("RequestId: " + e.getRequestId());
        }
    }
}

Python

# -*- coding: utf-8 -*-

from aliyunsdkcore import client
from aliyunsdkcore.request import CommonRequest
import json
import oss2
import os

# 從環境變數中擷取步驟1.1產生的RAM使用者的存取金鑰(AccessKey ID和AccessKey Secret)。
access_key_id = os.getenv("ACCESS_KEY_ID")
access_key_secret = os.getenv("ACCESS_KEY_SECRET")
# 從環境變數中擷取步驟1.3產生的RAM角色的RamRoleArn。
role_arn = os.getenv("RAM_ROLE_ARN")

# 建立權限原則。
clt = client.AcsClient(access_key_id, access_key_secret, 'cn-hangzhou')
request = CommonRequest(product="Sts", version='2015-04-01', action_name='AssumeRole')
request.set_method('POST')
request.set_protocol_type('https')
request.add_query_param('RoleArn', role_arn)
# 指定自訂角色會話名稱,用來區分不同的令牌,例如填寫為sessiontest。
request.add_query_param('RoleSessionName', 'sessiontest')
# 指定STS臨時訪問憑證到期時間為3600秒。
request.add_query_param('DurationSeconds', '3600')
request.set_accept_format('JSON')

body = clt.do_action_with_exception(request)

# 使用RAM使用者的AccessKey ID和AccessKey Secret向STS申請臨時訪問憑證。
token = json.loads(oss2.to_unicode(body))
# 列印STS返回的臨時存取金鑰(AccessKey ID和AccessKey Secret)、安全性權杖(SecurityToken)以及臨時訪問憑證到期時間(Expiration)。
print('AccessKeyId: ' + token['Credentials']['AccessKeyId'])
print('AccessKeySecret: ' + token['Credentials']['AccessKeySecret'])
print('SecurityToken: ' + token['Credentials']['SecurityToken'])
print('Expiration: ' + token['Credentials']['Expiration'])

Node.js

const { STS } = require('ali-oss');
const express = require("express");
const app = express();

app.get('/sts', (req, res) => {
 let sts = new STS({
  // 從環境變數中擷取步驟1.1產生的RAM使用者的存取金鑰(AccessKey ID和AccessKey Secret)。
   accessKeyId : process.env.ACCESS_KEY_ID,
   accessKeySecret : process.env.ACCESS_KEY_SECRET
});
  // process.env.RAM_ROLE_ARN為從環境變數中擷取步驟1.3產生的RAM角色的RamRoleArn。
  // policy填寫自訂權限原則,用於進一步限制STS臨時訪問憑證的許可權。如果不指定Policy,則返回的STS臨時訪問憑證預設擁有指定角色的所有許可權。
  // 臨時訪問憑證最後獲得的許可權是步驟4設定的角色許可權和該Policy設定許可權的交集。
  // expiration用於設定臨時訪問憑證有效時間單位為秒,最小值為900,最大值以當前角色設定的最大會話時間為準。本樣本指定有效時間為3600秒。
  // sessionName用於自訂角色會話名稱,用來區分不同的令牌,例如填寫為sessiontest。
  sts.assumeRole('process.env.RAM_ROLE_ARN', ``, '3600', '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")
})

Go

package main

import (
    "fmt"
    "os"

    openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client"
    sts20150401 "github.com/alibabacloud-go/sts-20150401/v2/client"
    util "github.com/alibabacloud-go/tea-utils/v2/service"
    "github.com/alibabacloud-go/tea/tea"
)

func main() {
    // 從環境變數中擷取步驟1.1產生的RAM使用者的存取金鑰(AccessKey ID和AccessKey Secret)。
    accessKeyId := os.Getenv("ACCESS_KEY_ID")
    accessKeySecret := os.Getenv("ACCESS_KEY_SECRET")
    // 從環境變數中擷取步驟1.3產生的RAM角色的RamRoleArn。
    roleArn := os.Getenv("RAM_ROLE_ARN")

    // 建立權限原則用戶端。
    config := &openapi.Config{
        // 必填,步驟1.1擷取到的 AccessKey ID。
        AccessKeyId: tea.String(accessKeyId),
        // 必填,步驟1.1擷取到的 AccessKey Secret。
        AccessKeySecret: tea.String(accessKeySecret),
    }
    // Endpoint 請參考 https://api.aliyun.com/product/Sts
    config.Endpoint = tea.String("sts.cn-hangzhou.aliyuncs.com")
    client, err := sts20150401.NewClient(config)
    if err != nil {
        fmt.Printf("Failed to create client: %v\n", err)
        return
    }

    // 使用RAM使用者的AccessKey ID和AccessKey Secret向STS申請臨時訪問憑證。
    request := &sts20150401.AssumeRoleRequest{
        // 指定STS臨時訪問憑證到期時間為3600秒。
        DurationSeconds: tea.Int64(3600),
        // 從環境變數中擷取步驟1.3產生的RAM角色的RamRoleArn。
        RoleArn: tea.String(roleArn),
        // 指定自訂角色會話名稱,這裡使用和第一段代碼一致的 examplename
        RoleSessionName: tea.String("examplename"),
    }
    response, err := client.AssumeRoleWithOptions(request, &util.RuntimeOptions{})
    if err != nil {
        fmt.Printf("Failed to assume role: %v\n", err)
        return
    }

    // 列印STS返回的臨時存取金鑰(AccessKey ID和AccessKey Secret)、安全性權杖(SecurityToken)以及臨時訪問憑證到期時間(Expiration)。
    credentials := response.Body.Credentials
    fmt.Println("AccessKeyId: " + tea.StringValue(credentials.AccessKeyId))
    fmt.Println("AccessKeySecret: " + tea.StringValue(credentials.AccessKeySecret))
    fmt.Println("SecurityToken: " + tea.StringValue(credentials.SecurityToken))
    fmt.Println("Expiration: " + tea.StringValue(credentials.Expiration))
}

php

<?php
require __DIR__ . '/vendor/autoload.php';

use AlibabaCloud\Client\AlibabaCloud;
use AlibabaCloud\Client\Exception\ClientException;
use AlibabaCloud\Client\Exception\ServerException;
use AlibabaCloud\Sts\Sts;

// 從環境變數中擷取步驟1.1產生的RAM使用者的存取金鑰(AccessKey ID和AccessKey Secret)。
$accessKeyId = getenv("ACCESS_KEY_ID");
$accessKeySecret = getenv("ACCESS_KEY_SECRET");
// 從環境變數中擷取步驟1.3產生的RAM角色的RamRoleArn。
$roleArn = getenv("RAM_ROLE_ARN");

// 初始化阿里雲用戶端。
AlibabaCloud::accessKeyClient($accessKeyId, $accessKeySecret)
    ->regionId('cn-hangzhou')
    ->asDefaultClient();

try {
    // 建立STS請求。
    $result = Sts::v20150401()
        ->assumeRole()
        // 設定角色ARN。
        ->withRoleArn($roleArn)
        // 指定自訂角色會話名稱,用來區分不同的令牌。
        ->withRoleSessionName('sessiontest')
        // 指定STS臨時訪問憑證到期時間為3600秒。
        ->withDurationSeconds(3600)
        ->request();

    // 擷取響應中的憑證資訊。
    $credentials = $result['Credentials'];

    // 列印STS返回的臨時存取金鑰(AccessKey ID和AccessKey Secret)、安全性權杖(SecurityToken)以及臨時訪問憑證到期時間(Expiration)。
    echo 'AccessKeyId: ' . $credentials['AccessKeyId'] . PHP_EOL;
    echo 'AccessKeySecret: ' . $credentials['AccessKeySecret'] . PHP_EOL;
    echo 'SecurityToken: ' . $credentials['SecurityToken'] . PHP_EOL;
    echo 'Expiration: ' . $credentials['Expiration'] . PHP_EOL;
} catch (ClientException $e) {
    // 處理用戶端異常。
    echo $e->getErrorMessage() . PHP_EOL;
} catch (ServerException $e) {
    // 處理服務端異常。
    echo $e->getErrorMessage() . PHP_EOL;
}

Ruby

require 'sinatra'
require 'base64'
require 'open-uri'
require 'cgi'
require 'openssl'
require 'json'
require 'sinatra/reloader'
require 'sinatra/content_for'
require 'aliyunsdkcore'

# 設定public檔案夾路徑為當前檔案夾下的templates檔案夾。
set :public_folder, File.dirname(__FILE__) + '/templates'

def get_sts_token_for_oss_upload()
  client = RPCClient.new(
    # 從環境變數中擷取步驟1.1產生的RAM使用者的存取金鑰(AccessKey ID和AccessKey Secret)。
    access_key_id: ENV['ACCESS_KEY_ID'],
    access_key_secret: ENV['ACCESS_KEY_SECRET'],
    endpoint: 'https://sts.cn-hangzhou.aliyuncs.com',
    api_version: '2015-04-01'
  )
  response = client.request(
    action: 'AssumeRole',
    params: {
      # 從環境變數中擷取步驟1.3產生的RAM角色的RamRoleArn。
      "RoleArn": ENV['RAM_ROLE_ARN'],
      # 指定STS臨時訪問憑證到期時間為3600秒。
      "DurationSeconds": 3600,
      # sessionName用於自訂角色會話名稱,用來區分不同的令牌,例如填寫為sessiontest。
      "RoleSessionName": "sessiontest"
    },
    opts: {
      method: 'POST',
      format_params: true
    }
  )
end

if ARGV.length == 1 
  $server_port = ARGV[0]
elsif ARGV.length == 2
  $server_ip = ARGV[0]
  $server_port = ARGV[1]
end

$server_ip = "0.0.0.0"
$server_port = 8000

puts "App server is running on: http://#{$server_ip}:#{$server_port}"

set :bind, $server_ip
set :port, $server_port

get '/get_sts_token_for_oss_upload' do
  token = get_sts_token_for_oss_upload()
  response = {
    "AccessKeyId" => token["Credentials"]["AccessKeyId"],
    "AccessKeySecret" => token["Credentials"]["AccessKeySecret"],
    "SecurityToken" => token["Credentials"]["SecurityToken"],
    "Expiration" => token["Credentials"]["Expiration"]
  }
  response.to_json
end

get '/*' do
  puts "********************* GET "
  send_file File.join(settings.public_folder, 'index.html')
end
  • 已擷取到STS臨時訪問憑證,詳情如下所示

    說明
    • 一個阿里雲帳號及該帳號下的RAM使用者、RAM角色,調用STS服務擷取臨時訪問憑證最多100次/秒。在並發數較大的情況下,建議在有效期間內複用臨時訪問憑證。

    • STS臨時訪問憑證的有效時間採用UTC(國際標準時間)格式。UTC時間與北京時間有8小時時差,為正常情況。例如:臨時訪問憑證到期時間是2024-04-18T11:33:40Z,說明臨時訪問憑證將在北京時間2024年4月18日19時33分40秒之前到期。

    {
      "AccessKeyId": "STS.NTP*******************oU35V",
      "AccessKeySecret": "3dZnC*********************************C34hwJuaPu4",
      "SecurityToken": "CAISv************************************************************************************************************************************CAA",
      "Expiration": "2024-**-*****:**:50Z"
    }
  • 若您需要對RAM角色許可權進行更細粒度的配置,可參考以下內容。

    如果您希望臨時訪問憑證在獲得角色擁有的許可權後,進一步限制許可權範圍,例如角色被授予了上傳檔案到examplebucket的許可權,您需要限制臨時訪問憑證只能向該Bucket下的某個目錄上傳檔案,您可以通過參考以下樣本設定policy。

    // 以下Policy用於限制僅允許使用臨時訪問憑證向examplebucket下的src目錄上傳檔案。
    // 臨時訪問憑證最後獲得的許可權是步驟4設定的角色許可權和該Policy設定許可權的交集,即僅允許將檔案上傳至examplebucket下的src目錄。      
    String policy = "{\n" +
                    "    \"Version\": \"1\", \n" +
                    "    \"Statement\": [\n" +
                    "        {\n" +
                    "            \"Action\": [\n" +
                    "                \"oss:PutObject\"\n" +
                    "            ], \n" +
                    "            \"Resource\": [\n" +
                    "                \"acs:oss:*:*:examplebucket/src/*\" \n" +
                    "            ], \n" +
                    "            \"Effect\": \"Allow\"\n" +
                    "        }\n" +
                    "    ]\n" +
                    "}";

步驟二:企業B使用臨時訪問憑證上傳檔案到OSS

以下樣本展示了如何在臨時訪問憑證有效期間(Expiration)到期之前,使用臨時訪問憑證上傳檔案至OSS。關於SDK的安裝,以及其他程式設計語言使用臨時訪問憑證將檔案上傳至Object Storage Service的程式碼範例,請參見SDK參考

Java

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.PutObjectRequest;
import com.aliyuncs.exceptions.ClientException;

import java.io.File;

public class Demo {
    public static void main(String[] args) throws ClientException {
    // OSS訪問網域名稱。以華東1(杭州)地區為例,填寫為https://oss-cn-hangzhou.aliyuncs.com。其它Region請按實際情況填寫。
     String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
    // 從環境變數中擷取步驟1.5產生的臨時存取金鑰AccessKey ID和AccessKey Secret,非阿里雲帳號AccessKey ID和AccessKey Secret。
    String accessKeyId = System.getenv("ACCESS_KEY_ID");
    String accessKeySecret = System.getenv("ACCESS_KEY_SECRET");
    // 從環境變數中擷取步驟1.5產生的安全性權杖SecurityToken。
    String securityToken = System.getenv("STS_Token");
    
    // 建立OSSClient執行個體。
    OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret, securityToken);
    // 將本地檔案exampletest.txt上傳至examplebucket。
    PutObjectRequest putObjectRequest = new PutObjectRequest("examplebucket", "exampletest.txt", new File("D:\\localpath\\exampletest.txt"));
    
    // ObjectMetadata metadata = new ObjectMetadata();
    // 上傳檔案時設定儲存類型。
    // metadata.setHeader(OSSHeaders.OSS_STORAGE_CLASS, StorageClass.Standard.toString());
    // 上傳檔案時設定讀寫權限ACL。
    // metadata.setObjectAcl(CannedAccessControlList.Private);
    // putObjectRequest.setMetadata(metadata);

try {
     // 上傳檔案。
     ossClient.putObject(putObjectRequest);
    } catch (OSSException oe) {
        System.out.println("Caught an OSSException, which means your request made it to OSS, "
                + "but was rejected with an error response for some reason.");
        System.out.println("Error Message:" + oe.getErrorMessage());
        System.out.println("Error Code:" + oe.getErrorCode());
        System.out.println("Request ID:" + oe.getRequestId());
        System.out.println("Host ID:" + oe.getHostId());
    } finally {
        if (ossClient != null) {
            ossClient.shutdown();
        }
    }
}
}

Python

# -*- coding: utf-8 -*-
import oss2

# yourEndpoint填寫Bucket所在地區對應的Endpoint。以華東1(杭州)為例,Endpoint填寫為https://oss-cn-hangzhou.aliyuncs.com。
endpoint = 'https://oss-cn-hangzhou.aliyuncs.com'
# 填寫步驟1.5產生的臨時存取金鑰AccessKey ID和AccessKey Secret,非阿里雲帳號AccessKey ID和AccessKey Secret。
sts_access_key_id = 'yourAccessKeyId'
sts_access_key_secret = 'yourAccessKeySecret'
# 填寫Bucket名稱。
bucket_name = 'examplebucket'
# 填寫Object完整路徑和字串。Object完整路徑中不能包含Bucket名稱。 
object_name = 'examplebt.txt'
# 填寫步驟1.5產生的STS安全性權杖(SecurityToken)。
security_token = 'yourSecurityToken'
# 使用臨時訪問憑證中的認證資訊初始化StsAuth執行個體。
auth = oss2.StsAuth(sts_access_key_id,
                    sts_access_key_secret,
                    security_token)
# 使用StsAuth執行個體初始化儲存空間。
bucket = oss2.Bucket(auth, endpoint, bucket_name)
# 上傳Object。
result = bucket.put_object(object_name, "hello world")
print(result.status)

Node.js

說明

此步驟中的樣本需要依賴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',
      // 填寫步驟1.5產生的臨時存取金鑰AccessKey ID和AccessKey Secret,非阿里雲帳號AccessKey ID和AccessKey Secret。
      accessKeyId: token.data.AccessKeyId,
      accessKeySecret: token.data.AccessKeySecret,
      // 填寫步驟1.5產生的STS安全性權杖(SecurityToken)。
      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()

Go

package main

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

func main() {
    // 從環境變數中擷取步驟1.5產生的臨時訪問憑證。運行本程式碼範例之前,請確保已設定環境變數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")
}

php

<?php
// 引入自動負載檔案
if (is_file(__DIR__ . 'autoload.php')) {
    require_once __DIR__ . 'autoload.php';
}
if (is_file(__DIR__ . '/vendor/autoload.php')) {
    require_once __DIR__ . '/vendor/autoload.php';
}

use OSS\OssClient;
use OSS\Core\OssException;

// 填寫步驟1.5產生的臨時存取金鑰AccessKey ID和AccessKey Secret,非阿里雲帳號AccessKey ID和AccessKey Secret。
$stsAccessKeyId = "yourAccessKeyId";
$stsAccessKeySecret = "yourAccessKeySecret";
// 填寫步驟1.5產生的STS安全性權杖(SecurityToken)。
$securityToken = "yourSecurityToken";
// yourEndpoint填寫Bucket所在地區對應的Endpoint。以華東1(杭州)為例,Endpoint填寫為https://oss-cn-hangzhou.aliyuncs.com。
$endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
// 填寫Bucket名稱。
$bucket = "examplebucket";
// 填寫不包含Bucket名稱在內的Object完整路徑,這裡作為上傳到OSS後的檔案名稱。
$object = "examplebt.txt";
// 填寫本地要上傳的檔案的完整路徑。
$localFilePath = "/path/to/your/local/file.txt";

try {
    // 使用臨時訪問憑證建立OssClient執行個體。
    $ossClient = new OssClient($stsAccessKeyId, $stsAccessKeySecret, $endpoint, false, $securityToken);

    // 上傳檔案到OSS。
    $result = $ossClient->uploadFile($bucket, $object, $localFilePath);
    
    // 輸出上傳結果。
    printf("檔案上傳成功,ETag: %s\n", $result['etag']);
} catch (OssException $e) {
    // 處理異常。
    printf("檔案上傳失敗,錯誤資訊: %s\n", $e->getMessage());
}

Ruby

require 'aliyun/sts'
require 'aliyun/oss'

client = Aliyun::OSS::Client.new(
  # Endpoint以華東1(杭州)為例,其它Region請按實際情況填寫。
  endpoint: 'https://oss-cn-hangzhou.aliyuncs.com',
  # 填寫步驟1.5產生的臨時存取金鑰AccessKey ID和AccessKey Secret,非阿里雲帳號AccessKey ID和AccessKey Secret。
  access_key_id: 'token.access_key_id',
  access_key_secret: 'token.access_key_secret',
  # 填寫步驟1.5產生的STS安全性權杖(SecurityToken)。
  sts_token: 'token.security_token'
  )
# 填寫Bucket名稱,例如examplebucket。
bucket = client.get_bucket('examplebucket')
# 上傳檔案。
bucket.put_object('exampleobject.txt', :file => 'D:\test.txt')

常見問題

報錯You are not authorized to do this action. You should be authorized by RAM.如何處理?

步驟1.5中使用RAM使用者扮演RAM角色擷取臨時訪問憑證時,必須使用RAM使用者的存取金鑰(AccessKey ID和AccessKey Secret),不能使用阿里雲帳號的存取金鑰發起請求。

報錯The Min/Max value of DurationSeconds is 15min/1hr.如何處理?

報錯原因是設定的臨時訪問憑證有效期間超出允許的時間範圍。請遵循以下原則設定有效期間:

  • 如果沒有自訂角色最大會話時間,則當前角色會話時間預設值為3600秒。此時,通過durationSeconds設定的臨時訪問憑證有效時間允許的最小值為900秒,最大值為3600秒。

  • 如果自訂了角色最大會話時間,則通過durationSeconds設定的臨時訪問憑證有效時間的最小值為900秒,最大值以角色最大會話時間為準。角色會話時間允許設定的取值範圍為3600秒~43200秒。

您可以通過RAM控制台查看角色最大會話時間。具體步驟,請參見查看RAM角色

報錯The security token you provided is invalid.如何處理?

請確保完整填寫步驟1.5擷取到的SecurityToken。

報錯The OSS Access Key Id you provided does not exist in our records.如何處理?

臨時訪問憑證已到期,到期後自動失效。請使用臨時存取金鑰(AccessKeyId和AccessKeySecret)向App伺服器申請新的臨時訪問憑證。具體操作,請參見步驟1.5

報錯AccessDenied : Anonymous access is forbidden for this operation.如何處理?

通過步驟1.5擷取臨時訪問憑證時,您需要使用填寫步驟1.1產生的RAM使用者存取金鑰AccessKey ID和AccessKey Secret,非阿里雲帳號AccessKey ID和AccessKey Secret。

報錯NoSuchBucket如何處理?

出現該報錯的原因是指定的Bucket不存在。請檢查並配置正確的Bucket名稱。

通過臨時訪問憑證操作OSS資源時報錯You have no right to access this object because of bucket acl.如何處理?

出現該報錯通常是Policy設定錯誤。關於Policy中涉及各元素的填寫要求,請參見RAM Policy。如果您需要擷取具有分區上傳、追加上傳等許可權的臨時訪問憑證,您需要通過Policy中的Action元素授予對應許可權。關於OSS Action的更多資訊,請參見OSS Action分類

通過臨時訪問憑證操作OSS資源時報錯Access denied by authorizer's policy.如何處理?

出現該報錯通常是無許可權執行相關操作。申請臨時訪問憑證之前,需要建立用於擷取臨時訪問憑證的RAM角色並完成角色授權(本文檔步驟1.4)。向STS伺服器發起扮演該角色的請求,以擷取臨時訪問憑證時可以通過policy參數進一步限制臨時訪問憑證的許可權(本文檔步驟1.5)。

  • 如果設定policy,則臨時訪問憑證最終的許可權是RAM角色權限原則與policy權限原則的交集。

    • 樣本1

      如下圖所示,A代表RAM角色的許可權,B代表通過policy參數設定的許可權,C代表臨時訪問憑證最終的許可權。

      1.jpg

    • 樣本2

      如下圖所示,A代表RAM角色許可權,B代表通過policy參數設定的許可權,且policy參數設定的許可權是RAM角色許可權的子集。因此,B代表臨時訪問憑證的最終許可權。

      2.jpg

  • 如果不設定policy,則臨時訪問憑證具有與RAM角色相同的權限原則。

報錯The bucket you are attempting to access must be addressed using the specified endpoint.如何處理?

出現該報錯的原因是步驟二中的Endpoint參數填寫錯誤。您需要根據Bucket所在Region填寫對應的Endpoint。關於Region與Endpoint對應關係的說明,請參見OSS地區和訪問網域名稱

是否支援同時擷取多個臨時訪問憑證?

支援。發起一次請求僅返回一個臨時訪問憑證。如果您希望擷取多個臨時訪問憑證,您需要發起多次請求。在有效期間內,您可以同時使用擷取到的多個臨時訪問憑證。

報錯時間格式不正確如何處理?

如果調用時報錯時間格式不正確,可能是由於Timestamp參數中間多餘空格,請排查修改。

請求的時間戳記日期格式按照ISO8601標準表示,並需要使用UTC時間。格式為:YYYY-MM-DDThh:mm:ssZ。例如,2014-05-26T12:00:00Z(為北京時間2014年5月26日20點0分0秒)。

返回0003-0000301怎麼處理?

返回0003-0000301原因是臨時訪問憑證不具有執行OSS相關操作的許可權,解決方案請參見0003-00000301

相關文檔

  • 如果您希望從服務端擷取STS臨時訪問憑證後,通過用戶端上傳檔案,且上傳檔案時需要限制上傳的檔案大小、上傳的檔案類型、上傳到Bucket的具體路徑等,請參見用戶端直傳

  • 通過STS臨時訪問憑證授權上傳檔案到OSS後,您可以通過簽名URL的方式將檔案分享給第三方使用者進行預覽或者下載。具體操作,請參見使用預簽名URL下載檔案