全部产品
Search
文档中心

对象存储 OSS:使用STS临时访问凭证访问OSS

更新时间:Sep 19, 2023

您可以通过STS服务给其他用户颁发一个临时访问凭证。该用户可使用临时访问凭证在规定时间内访问您的OSS资源。临时访问凭证无需透露您的长期密钥,使您的OSS资源访问更加安全。

前提条件

已确保当前账号为阿里云账号或者被授予AliyunRAMFullAccess权限的RAM用户。关于为RAM用户授权的具体步骤,请参见为RAM用户授权

适用场景

假设您是一个移动App开发者,希望使用阿里云OSS服务来保存App的终端用户数据,并且要保证每个App用户之间的数据隔离。此时,您可以使用STS授权用户直接访问OSS。

使用STS授权用户直接访问OSS的流程如下:

sts
  1. App用户登录。App用户和云账号无关,它是App的终端用户,App服务器支持App用户登录。对于每个有效的App用户来说,需要App服务器能定义出每个App用户的最小访问权限。

  2. App服务器请求STS服务获取一个安全令牌(SecurityToken)。在调用STS之前,App服务器需要确定App用户的最小访问权限(用RAM Policy来自定义授权策略)以及凭证的过期时间。然后通过扮演角色(AssumeRole)来获取一个代表角色身份的安全令牌(SecurityToken)。

  3. STS返回给App服务器一个临时访问凭证,包括一个安全令牌(SecurityToken)、临时访问密钥(AccessKeyId和AccessKeySecret)以及过期时间。

  4. App服务器将临时访问凭证返回给App客户端,App客户端可以缓存这个凭证。当凭证失效时,App客户端需要向App服务器申请新的临时访问凭证。例如,临时访问凭证有效期为1小时,那么App客户端可以每30分钟向App服务器请求更新临时访问凭证。

  5. App客户端使用本地缓存的临时访问凭证去请求OSS API。OSS收到访问请求后,会通过STS服务来验证访问凭证,正确响应用户请求。

步骤一:创建RAM用户

  1. 登录RAM控制台

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

  3. 单击创建用户

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

  5. 访问方式区域下,选择OpenAPI调用访问,然后单击确定

  6. 单击复制,保存访问密钥(AccessKey ID 和 AccessKey Secret)。

步骤二:为RAM用户授予请求AssumeRole的权限

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

  2. 添加权限页面,选择AliyunSTSAssumeRoleAccess系统策略。image.png

  3. 单击确定

步骤三:创建用于获取临时访问凭证的角色

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

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

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

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

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

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

步骤四:为角色授予上传文件的权限

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

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

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

    3. 创建权限策略页面,单击脚本编辑,然后在策略文档输入框中赋予角色向目标存储空间examplebucket下的src以及dest目录上传文件的权限。具体配置示例如下。

      警告

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

      {
          "Version": "1",
          "Statement": [
           {
                 "Effect": "Allow",
                 "Action": [
                   "oss:PutObject"
                 ],
                 "Resource": [
                   "acs:oss:*:*:examplebucket/src/*",
                   "acs:oss:*:*:examplebucket/dest/*"
                 ]
           }
          ]
      }
    4. 策略配置完成后,单击继续编辑基本信息

    5. 基本信息区域,填写策略名称RamTestPolicy,然后单击确定

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

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

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

    3. 单击RAM角色RamOssTest右侧的添加权限

    4. 添加权限页面下的自定义策略页签,选择已创建的自定义权限策略RamTestPolicy

    5. 单击确定

步骤五:获取临时访问凭证

使用STS SDK

您可以使用STS SDK来获取临时访问凭证。

本文以Java为例,说明如何使用STS SDK获取具有简单上传(oss:PutObject)权限的临时访问凭证。关于更多语言的STS SDK示例,请参见STS SDK概览

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。       
        String endpoint = "yourStsEndpoint";
        // 从环境变量中获取步骤1生成的RAM用户的访问密钥(AccessKey ID和AccessKey Secret)。
        String accessKeyId = System.getenv("OSS_ACCESS_KEY_ID");
        String accessKeySecret = System.getenv("OSS_ACCESS_KEY_SECRET");
        // 从环境变量中获取步骤3生成的RAM角色的RamRoleArn。
        String roleArn = System.getenv("OSS_STS_ROLE_ARN");
        // 自定义角色会话名称,用来区分不同的令牌,例如可填写为SessionTest。        
        String roleSessionName = "yourRoleSessionName";
        // 以下Policy用于限制仅允许使用临时访问凭证向目标存储空间examplebucket下的src目录上传文件。
        // 临时访问凭证最后获得的权限是步骤4设置的角色权限和该Policy设置权限的交集,即仅允许将文件上传至目标存储空间examplebucket下的src目录。
        // 如果policy为空,则用户将获得该角色下所有权限。
        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" +
                "}";
        // 设置临时访问凭证的有效时间为3600秒。
        Long durationSeconds = 3600L;
        try {
            // regionId表示RAM的地域ID。以华东1(杭州)地域为例,regionID填写为cn-hangzhou。也可以保留默认值,默认值为空字符串("")。
            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());
        }
    }
}

参数

示例值

说明

endpoint

sts.cn-hangzhou.aliyuncs.com

STS服务接入点。您可以通过公网或者VPC接入STS服务。关于STS提供的服务接入点,请参见服务接入点

accessKeyId

LTAI5tJHezdULrXcczCW****

步骤一生成的RAM用户访问密钥AccessKey ID。

accessKeySecret

CTkGhP9xUpMR5IWj4WRZTQ2SR****

步骤一生成的RAM用户访问密钥AccessKey Secret。

roleArn

acs:ram::137918634****:role/ramosstest

步骤三获取的角色ARN。

roleSessionName

SessionTest

角色会话名称。

该参数为用户自定义参数。通常设置为调用该API的用户身份。

长度为2~64个字符,可包含英文字母、数字、半角句号(.)、at(@)、短划线(-)和下划线(_)

policy

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

为STS Token额外添加的一个权限策略,进一步限制STS Token的权限。具体如下:

  • 如果指定该权限策略,则STS Token最终的权限策略取RAM角色权限策略与该权限策略的交集。

  • 如果不指定该权限策略,则STS Token最终的权限策略取RAM角色的权限策略。

关于Policy中涉及各元素的填写要求,请参见RAM Policy概述

如果您需要获取具有分片上传、追加上传等权限的临时访问凭证,您需要通过Policy中的Action元素授予对应权限。关于OSS Action的更多信息,请参见OSS Action分类

durationSeconds

3600

临时访问凭证的有效时间。

单位为秒。最小值为900。最大值以当前角色设定的最大会话时间为准。当前角色最大会话时间取值范围为3600秒~43200秒,默认值为3600秒。详情请参见设置角色最大会话时间

在上传大文件或者其他较耗时的使用场景中,建议合理设置临时访问凭证的有效时间,确保在完成目标任务前无需反复调用STS服务以获取临时访问凭证。

使用REST API

您可以通过调用STS服务的AssumeRole接口来获取临时访问凭证。

步骤六:使用临时访问凭证上传文件至OSS

以Java SDK 3.12.0版本为例,将本地D:\\localpath路径下的exampletest.txt文件上传至存储空间examplebucket下的src目录的示例代码如下:

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 {
// Endpoint以杭州为例,其它Region请按实际情况填写。
 String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
// 从环境变量中获取步骤5生成的临时访问密钥AccessKey ID和AccessKey Secret,非阿里云账号AccessKey ID和AccessKey Secret。
String accessKeyId = System.getenv("OSS_ACCESS_KEY_ID");
String accessKeySecret = System.getenv("OSS_ACCESS_KEY_SECRET");
// 从环境变量中获取步骤5生成的安全令牌SecurityToken。
String securityToken = System.getenv("OSS_SESSION_TOKEN");

// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret, securityToken);
// 将本地文件exampletest.txt上传至目标存储空间examplebucket下的src目录。
PutObjectRequest putObjectRequest = new PutObjectRequest("examplebucket", "src/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();
        }
    }
}
}

关于上传文件时支持设置的存储类型的更多信息,请参见存储类型概述。关于上传文件时支持设置的读写权限ACL的更多信息,请参见Object ACL

Object上传成功后,关于如何获取访问URL的具体操作,请参见获取单个或多个文件的URL

常见问题

报错The security token you provided is invalid.如何处理?

请确保完整填写步骤五获取到的SecurityToken。

报错The OSS Access Key Id you provided does not exist in our records.如何处理?

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

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

通过步骤五获取临时访问凭证时,您需要使用填写步骤一生成的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设置错误,例如Resource填写不完整。关于Policy涉及的各个元素的更多信息,请参见RAM Policy概述

通过临时访问凭证操作OSS资源时报错Access denied by authorizer's policy.如何处理?

出现该报错通常是无权限执行相关操作。临时访问凭证最终获取的权限是步骤四设置的角色权限和步骤五中Policy设置权限的交集。请通过以下示例检查您在这两个步骤中设置的权限交集。

  • 示例一

    步骤四设置的角色权限为AliyunOSSFullAccess系统权限,步骤五Policy中设置了oss:PutObject权限,则临时访问凭证最终获取的权限为oss:PutObject,即仅支持执行向指定Bucket上传文件的操作。

  • 示例二

    步骤四设置的角色权限为oss:PutObject系统权限,步骤五Policy中设置了oss:GetObject权限,则临时访问凭证最终未获取任何权限,即无法向指定Bucket执行任何操作。

报错The bucket you are attempting to access must be addressed using the specified endpoint.如何处理?

出现该报错的原因是步骤六中的Endpoint参数填写错误。您需要根据Bucket所在Region填写对应的Endpoint。关于Region与Endpoint对应关系的说明,请参见访问域名和数据中心

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

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

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

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

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