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

重要

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

您可以通过STS服务为其他用户颁发一个临时访问凭证,用户通过临时访问凭证可以在限定的有效期内,以符合策略规定的权限访问OSS资源。超过有效期后,该凭证自动失效,无法继续通过该凭证访问OSS资源,确保了访问控制的灵活性和时效性。

操作视频

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

使用场景

某电商企业A把海量商品数据存放在阿里云OSS中。供应商企业B需要定期向AOSS上传数据,并通过自己的系统与企业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拿到该凭证后,即可将数据上传至企业AOSS中。

前提条件

企业A已创建Bucket。具体操作,请参见创建存储空间

步骤一:企业A颁发临时访问凭证

1. 创建RAM用户

  1. 登录RAM控制台

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

  3. 单击创建用户

  4. 输入登录名称显示名称

  5. 访问方式区域下,选择使用永久 AccessKey 访问,然后单击确定

  6. 根据界面提示,完成安全验证。

  7. 复制访问密钥(AccessKey IDAccessKey Secret)。

    重要

    RAM用户的AccessKey Secret只在创建时显示,后续不支持查看,请妥善保管。

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

创建RAM用户后,您需要授予RAM用户通过扮演角色来调用STS服务的权限。

  1. 单击已创建RAM用户右侧对应的添加权限

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

    说明

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

    image.png

  3. 单击确认新增授权

3. 创建RAM角色

您需要创建RAM角色,用于定义RAM角色被扮演时,可以获得OSS服务的哪些访问权限。

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

  2. 单击创建角色,选择可信实体类型为阿里云账号,单击下一步

  3. 创建角色对话框,角色名称填写为RamOssTest,选择信任的云账号当前云账号

  4. 单击完成。角色创建完成后,单击关闭

  5. 角色页面,搜索框输入角色名称RamOssTest,然后单击RamOssTest

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

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

RAM角色附加一个或多个权限策略,明确RAM角色在被扮演时所能拥有的OSS资源访问权限。例如,如果希望RAM用户在扮演该角色后只能向OSS指定Bucket上传文件,则需要为角色添加写入权限的策略。

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

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

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

    3. 创建权限策略页面,单击脚本编辑,然后在策略文档输入框中赋予角色上传文件到examplebucket的权限。具体配置示例如下。

      警告

      以下示例仅供参考。您需要根据实际需求配置更细粒度的授权策略,防止出现权限过大的风险。关于更细粒度的授权策略配置详情,请参见通过RAMSTS服务向其他用户授权

      {
          "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)、临时访问密钥(AccessKeyIdAccessKeySecret)以及过期时间(Expiration)。您可以使用STS SDK获取具有简单上传(oss:PutObject)权限的临时访问凭证。

说明

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 (
    "encoding/json"
    "net/http"
    "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"
)

/**
 * 使用AK&SK初始化账号Client
 * @param accessKeyId
 * @param accessKeySecret
 * @return Client
 * @throws Exception
 */
func CreateClient(accessKeyId *string, accessKeySecret *string) (*sts20150401.Client, error) {
    config := &openapi.Config{
    // 必填,步骤1.1获取到的 AccessKey ID。 
    AccessKeyId: accessKeyId,
    // 必填,步骤1.1获取到的 AccessKey Secret。 
    AccessKeySecret: accessKeySecret,
    }
    // Endpoint 请参考 https://api.aliyun.com/product/Sts
    config.Endpoint = tea.String("sts.cn-hangzhou.aliyuncs.com")
    return sts20150401.NewClient(config)
}

func AssumeRole(client *sts20150401.Client) (*sts20150401.AssumeRoleResponse, error) {
    assumeRoleRequest := &sts20150401.AssumeRoleRequest{
    // 指定STS临时访问凭证过期时间为3600秒。 
    DurationSeconds: tea.Int64(3600),
    // 从环境变量中获取步骤1.3生成的RAM角色的RamRoleArn。
    RoleArn: tea.String(os.Getenv("RAM_ROLE_ARN")),
    // sessionName用于自定义角色会话名称,用来区分不同的令牌,例如填写为sessiontest。
    RoleSessionName: tea.String("sessiontest"),
    }
    return client.AssumeRoleWithOptions(assumeRoleRequest, &util.RuntimeOptions{})
}

func handler(w http.ResponseWriter, r *http.Request) {
    if r.URL.Path == "/" {
    http.ServeFile(w, r, "templates/index.html")
    return
    } else if r.URL.Path == "/get_sts_token_for_oss_upload" {
    // 从环境变量中获取步骤1.1生成的RAM用户的访问密钥(AccessKey ID和AccessKey Secret)。
    client, err := CreateClient(tea.String(os.Getenv("ACCESS_KEY_ID")), tea.String(os.Getenv("ACCESS_KEY_SECRET")))
    if err != nil {
    panic(err)
    }
    assumeRoleResponse, err := AssumeRole(client)
    if err != nil {
    panic(err)
    }
    responseBytes, err := json.Marshal(assumeRoleResponse)
    if err != nil {
    panic(err)
    }
    w.Header().Set("Content-Type", "application/json")
    w.Write(responseBytes)
    return
    }
    http.NotFound(w, r)
}

func main() {
    http.HandleFunc("/", handler)
    http.ListenAndServe(":8080", nil)
}

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("OSS_ACCESS_KEY_ID");
$accessKeySecret = getenv("OSS_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,说明临时访问凭证将在北京时间2024418193340秒之前过期。

    {
      "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的安装,以及其他编程语言使用临时访问凭证将文件上传至对象存储(OSS)的代码示例,请参见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名称。 
objecobject.txbucket_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 IDAccessKey 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.如何处理?

临时访问凭证已过期,过期后自动失效。请使用临时访问密钥(AccessKeyIdAccessKeySecret)向App服务器申请新的临时访问凭证。具体操作,请参见步骤1.5

报错AccessDenied : Anonymous access is forbidden for this operation.如何处理?

通过步骤1.5获取临时访问凭证时,您需要使用填写步骤1.1生成的RAM用户访问密钥AccessKey IDAccessKey Secret,非阿里云账号AccessKey IDAccessKey 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。关于RegionEndpoint对应关系的说明,请参见OSS地域和访问域名

是否支持同时获取多个临时访问凭证?

支持。发起一次请求仅返回一个临时访问凭证。如果您希望获取多个临时访问凭证,您需要发起多次请求。在有效期内,您可以同时使用获取到的多个临时访问凭证。

报错时间格式不正确如何处理?

如果调用时报错时间格式不正确,可能是由于Timestamp参数中间多余空格,请排查修改。

请求的时间戳日期格式按照ISO8601标准表示,并需要使用UTC时间。格式为:YYYY-MM-DDThh:mm:ssZ。例如,2014-05-26T12:00:00Z(为北京时间20145262000秒)。

返回0003-0000301怎么处理?

返回0003-0000301原因是临时访问凭证不具有执行OSS相关操作的权限,解决方案请参见0003-00000301

相关文档

  • 如果您希望从服务端获取STS临时访问凭证后,通过客户端上传文件,且上传文件时需要限制上传的文件大小、上传的文件类型、上传到Bucket的具体路径等,请参见客户端直传

  • 通过STS临时访问凭证授权上传文件到OSS后,您可以通过签名URL的方式将文件分享给第三方用户进行预览或者下载。具体操作,请参见使用签名URL下载文件