相关文章推荐
使用STS临时访问凭证访问OSS

使用STS临时访问凭证访问OSS

重要

本文中含有需要您注意的重要提示信息,忽略该信息可能对您的业务造成影响,请务必仔细阅读。

通过 STS 服务,您可以为用户生成临时访问凭证,使其在有效期内访问受策略限制的 OSS 资源。超过有效期后,凭证自动失效,无法继续访问 OSS 资源,确保了访问控制的灵活性和时效性。

操作视频

观看以下视频了解如何快速使用 STS 临时访问凭证访问 OSS。

使用场景

某电商企业 A 把海量商品数据存放在阿里云 OSS 中。供应商企业 B 需要定期向 A OSS 上传数据,并通过自己的系统与企业 A 的阿里云资源对接。

对于信息安全方面,企业 A 有如下需求:

  • 数据安全 :企业 A 不希望将固定访问密钥(AccessKey)泄露给企业 B,以免核心数据被非法获取和滥用。

  • 权限控制 :企业 A 希望暂时仅赋予企业 B 上传权限,后续再根据需求对权限进行动态调整,以实现对权限的精准控制。

  • 权限管理 :面对企业 B 以及后续的其他合作伙伴,企业 A 希望能够灵活地为每个合作伙伴或临时需求生成相应的凭证,而无需不断管理和配置固定的访问密钥(AccessKey)权限。

  • 限时访问控制 :企业 A 希望根据企业 B 的具体需求,限制其对数据访问的有效时间。到期后,企业 B 将自动失去访问权限,从而实现对数据交互时效性的严格控制。

方案概览

企业 A 通过临时访问凭证授权企业 B 安全地将文件上传到 OSS。

image

企业 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 仅在创建时显示,后续将无法查看。因此,强烈建议您及时下载包含访问密钥(AccessKey)的 CSV 文件,并妥善保存至本地。

    image

2. 为 RAM 用户授予请求 AssumeRole 的权限

创建完 RAM 用户后,使用 阿里云主账号 或拥有 访问控制(RAM)管理权限的 RAM 账号 授予该 RAM 用户通过扮演角色调用 STS 服务的权限。

  1. 登录 RAM 控制台

  2. 在左侧导航栏,选择 身份管理 > 用户 ,单击已创建 RAM 用户右侧对应的 添加权限

  3. 新增授权 页面,选择 AliyunSTSAssumeRoleAccess 系统策略。

    说明

    授予 RAM 用户调用 STS 服务 AssumeRole 接口的固定权限是 AliyunSTSAssumeRoleAccess ,与后续获取临时访问凭证以及通过临时访问凭证发起 OSS 请求所需权限无关。

    image

  4. 单击 确认新增授权

3. 创建 RAM 角色

使用 阿里云主账号 或拥有 访问控制(RAM)管理权限的 RAM 账号 创建 RAM 角色 用于定义 RAM 角色被扮演时,可以获得 OSS 服务的哪些访问权限。

  1. 登录 RAM 控制台

  2. 在左侧导航栏,选择 身份管理 > 角色

  3. 角色 页面,单击 创建角色

  4. 创建角色 页面,选择 信任主体类型 云账号 ,然后选择 信任主体名称 当前云账号 ,单击 确定

    image

  5. 创建角色 对话框,输入角色名称,然后单击 确定

  6. 单击 ARN 右侧的 复制 ,保存角色的 ARN。

    image

4. 为 RAM 角色授予上传文件的权限

创建完 RAM 角色后,使用 阿里云主账号 或拥有 访问控制(RAM)管理权限的 RAM 账号 RAM 角色附加一个或多个权限策略,明确 RAM 角色在被扮演时所能拥有的 OSS 资源访问权限。例如,如果希望 RAM 用户在扮演该角色后只能向 OSS 指定 Bucket 上传文件,则需要为角色添加写入权限的策略。

  1. 创建上传文件的自定义权限策略。

    1. 登录 RAM 控制台

    2. 在左侧导航栏,选择 权限管理 > 权限策略

    3. 权限策略 页面,单击 创建权限策略

    4. 创建权限策略 页面,单击 脚本编辑 ,然后在策略文档输入框中赋予角色上传文件到 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 说明

    5. 策略配置完成后,请单击 确定 按钮,然后在 创建权限策略 弹出框中填写策略名称(例如 RamTestPolicy ),确认信息无误后再次单击 确定

  2. RAM 角色 RamOssTest 授予自定义权限策略。

    1. 登录 RAM 控制台

    2. 在左侧导航栏,选择 身份管理 > 角色

    3. 角色 页面,找到目标 RAM 角色 RamOssTest

    4. 单击 RAM 角色 RamOssTest 右侧的 新增授权

    5. 新增授权 页面的 权限策略 模块中,选择策略类型为 自定义策略 ,随后在策略列表中选取已创建的自定义权限策略 RamTestPolicy

    6. 单击 确认新增授权

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"
    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
if ARGV.length == 1 
  $server_port = ARGV[0]
elsif ARGV.length == 2
  $server_ip = ARGV[0]
  $server_port = ARGV[1]
$server_ip = "127.0.0.1"  #如果需要监听其他地址如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
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.****************",
      "AccessKeySecret": "3dZn*******************************************",
      "SecurityToken": "CAIS*****************************************************************************************************************************************",
      "Expiration": "2024-**-*****:**:50Z"
    }
  • 若您需要对临时访问权限进行更细粒度的配置,可参考以下内容。

    如果您希望临时访问凭证在获得角色拥有的权限后,进一步限制权限范围,例如角色被授予了上传文件到 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 安装指南及各编程语言使用临时访问凭证操作 OSS(如文件上传、下载等)的代码示例,请参见 SDK 参考

Java

import com.aliyun.oss.*;
import com.aliyun.oss.common.auth.CredentialsProvider;
import com.aliyun.oss.common.auth.DefaultCredentialProvider;
import com.aliyun.oss.common.comm.SignVersion;
import com.aliyun.oss.model.PutObjectRequest;
import com.aliyun.oss.model.PutObjectResult;
import java.io.File;
public class Demo {
    public static void main(String[] args) throws Exception {
        // 请填写步骤1.5生成的临时访问密钥AccessKey ID、AccessKey Secret和SecurityToken,而非RAM用户的身份凭证信息
        // 请注意区分STS服务获取的AccessKey ID是以STS开头
        String accessKeyId = "yourSTSAccessKeyID";
        String accessKeySecret = "yourSTSAccessKeySecret";
        // 填写获取的STS安全令牌(SecurityToken)。
        String stsToken= "yourSecurityToken";
        // 使用DefaultCredentialProvider方法直接设置AK和SK
        CredentialsProvider credentialsProvider = new DefaultCredentialProvider(accessKeyId, accessKeySecret, stsToken);
        // 使用credentialsProvider初始化客户端
        ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
        // 显式声明使用 V4 签名算法
        clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);
        // 创建OSSClient实例。
        OSS ossClient = OSSClientBuilder.create()
                 // 请设置目的OSS访问域名  例如杭州地域:https://oss-cn-hangzhou.aliyuncs.com
                .endpoint("endpoint")
                .credentialsProvider(credentialsProvider)
                .clientConfiguration(clientBuilderConfiguration)
                // 请设置为目标Bucket所处region  例如杭州地域:cn-hangzhou
                .region("region")
                .build();
        try {
            // 创建PutObjectRequest对象,将本地文件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());
            // metadata.setObjectAcl(CannedAccessControlList.Private);
            // putObjectRequest.setMetadata(metadata);
            // 上传文件
            PutObjectResult result = 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());
        } catch (ClientException ce) {
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message:" + ce.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();

Python

Python SDK 目前提供 V2 V1 两个版本。V2 V1 基础上全面重构,简化了身份验证、请求重试、错误处理等底层操作,提供更灵活的参数配置和新的高级接口。请根据您的实际使用需求,参考如下示例。

V2 示例

import alibabacloud_oss_v2 as oss
def main():
    # 请填写步骤1.5生成的临时访问密钥AccessKey ID、AccessKey Secret和SecurityToken,而非RAM用户的身份凭证信息
    # 请注意区分STS服务获取的AccessKey ID是以STS开头
    sts_access_key_id = 'yourSTSAccessKeyID'
    sts_access_key_secret = 'yourSTSAccessKeySecret'
    # 填写获取的STS安全令牌(SecurityToken)
    sts_security_token = 'yourSecurityToken'
    # 创建静态凭证提供者,显式设置临时访问密钥AccessKey ID和AccessKey Secret,以及STS安全令牌
    credentials_provider = oss.credentials.StaticCredentialsProvider(
        access_key_id=sts_access_key_id,
        access_key_secret=sts_access_key_secret,
        security_token=sts_security_token,
    # 加载SDK的默认配置,并设置凭证提供者
    cfg = oss.config.load_default()
    cfg.credentials_provider = credentials_provider
    # 填写Bucket所在地域。以华东1(杭州)为例,Region填写为cn-hangzhou
    cfg.region = 'cn-hangzhou'
    # 使用配置好的信息创建OSS客户端
    client = oss.Client(cfg)
    # 待上传本地文件路径  例如 D:\\localpath\\exampletest.txt
    local_file_path = 'D:\\localpath\\exampletest.txt'
    with open(local_file_path, 'rb') as file:
        data = file.read()
    # 执行上传对象的请求,将本地文件exampletest.txt上传至examplebucket,指定存储空间名称、对象名称和上传文件
    result = client.put_object(oss.PutObjectRequest(
        # Bucket名称
        bucket='examplebucket',
        # 上传到Bucket中的对象名称
        key='exampletest.txt',
        body=data,
     # 输出请求的结果状态码、请求ID、内容MD5、ETag、CRC64校验码和版本ID,用于检查请求是否成功
    print(f'status code: {result.status_code},'
          f' request id: {result.request_id},'
          f' content md5: {result.content_md5},'
          f' etag: {result.etag},'
          f' hash crc64: {result.hash_crc64},'
          f' version id: {result.version_id},'
# 当此脚本被直接运行时,调用main函数
if __name__ == "__main__":
    main()  # 脚本入口,当文件被直接运行时调用main函数

V1 示例

# -*- 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)

Go

Go SDK 目前提供 V2 V1 两个版本。V2 V1 基础上全面重构,简化了身份验证、请求重试、错误处理等底层操作,提供更灵活的参数配置和新的高级接口。请根据您的实际使用需求,参考如下示例。

V2 示例

package main
import (
	"context"
	"log"
	"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss"
	"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss/credentials"
func main() {
	// 填写Bucket所在地域。以华东1(杭州)为例,Region填写为cn-hangzhou
	region := "cn-hangzhou"
	// 请填写步骤1.5生成的临时访问密钥AccessKey ID、AccessKey Secret和SecurityToken,而非RAM用户的身份凭证信息
        // 请注意区分STS服务获取的AccessKey ID是以STS开头
	accessKeyID := "yourSTSAccessKeyID"
	accessKeySecret := "yourSTSAccessKeySecret"
	// 填写获取的STS安全令牌(SecurityToken)
	stsToken := "yourSecurityToken"
	// 使用NewStaticCredentialsProvider方法直接设置AK、SK和STS Token
	provider := credentials.NewStaticCredentialsProvider(accessKeyID, accessKeySecret, stsToken)
	// 加载默认配置并设置凭证提供者和区域
	cfg := oss.LoadDefaultConfig().
		WithCredentialsProvider(provider).
		WithRegion(region)
	// 创建OSS客户端
	client := oss.NewClient(cfg)
	// 填写要上传的本地文件路径和文件名称,例如 D:\\localpath\\exampletest.txt
	localFile := "D:\\localpath\\exampletest.txt"
	// 创建上传对象的请求
	putRequest := &oss.PutObjectRequest{
		Bucket:       oss.Ptr("examplebucket"),      // Bucket名称
		Key:          oss.Ptr("exampletest.txt"),    // 上传到Bucket中的对象名称
		StorageClass: oss.StorageClassStandard, // 指定对象的存储类型为标准存储
		Acl:          oss.ObjectACLPrivate,     // 指定对象的访问权限为私有访问
		Metadata: map[string]string{
			"yourMetadataKey1": "yourMetadataValue1", // 设置对象的元数据
	// 执行上传对象的请求,将本地文件exampletest.txt上传至examplebucket
	result, err := client.PutObjectFromFile(context.TODO(), putRequest, localFile)
	if err != nil {
		log.Fatalf("failed to put object from file %v", err)
	// 打印上传对象的结果
	log.Printf("put object from file result:%#v\n", result)
}

V1 示例

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")
}

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.data.AccessKeyId,
          accessKeySecret: refreshToken.data.AccessKeySecret,
          stsToken: refreshToken.data.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()

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\Credentials\StaticCredentialsProvider;
use OSS\OssClient;
use OSS\Core\OssException;
try {
    // 请填写步骤1.5生成的临时访问密钥AccessKey ID、AccessKey Secret和SecurityToken,而非RAM用户的身份凭证信息
    // 请注意区分STS服务获取的AccessKey ID是以STS开头
    $accessKeyId = 'yourSTSAccessKeyID';
    $accessKeySecret = 'yourSTSAccessKeySecret';
    // 填写获取的STS安全令牌(SecurityToken)
    $securityToken = 'yourSecurityToken';
    // 使用StaticCredentialsProvider类创建凭证提供者
    $provider = new StaticCredentialsProvider($accessKeyId, $accessKeySecret, $securityToken);
    // 填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com
    $endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
    // 填写Bucket名称,例如examplebucket。
    $bucket= "examplebucket";
    // 填写上传到Bucket中的对象名称
    $object = "exampletest.txt";
    // 填写待上传本地文件路径,例如 D:\\localpath\\exampletest.txt
    $localFilePath = "D:\\localpath\\exampletest.txt";
    // 上传时可以设置相关的headers,例如设置访问权限为private、自定义元数据等
    $options = array(
        OssClient::OSS_HEADERS => array(
            'x-oss-object-acl' => 'private',
            'x-oss-meta-info' => 'yourinfo'
    $config = array(
        "provider" => $provider,
        "endpoint" => $endpoint,
        "signatureVersion" => OssClient::OSS_SIGNATURE_VERSION_V4,
        // 填写Bucket所在地域。以华东1(杭州)为例,Region填写为cn-hangzhou
        "region" => "cn-hangzhou"
    // 使用配置好的信息创建OSS客户端
    $ossClient = new OssClient($config);
     // 发送请求 将本地文件exampletest.txt上传至examplebucket
    $ossClient->putObject($bucket, $object, $localFilePath, $options);
} catch (OssException $e) {
    printf($e->getMessage() . "\n");
    return;
}

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 下载文件

 
推荐文章