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

220 阅读6分钟

使用STS临时访问凭证通过客户端直连OSS对象存储服务器

导论

最近在做项目的过程中使用到了阿里云OSS来存储客户端上传的文件,方法是直接将客户端上传的文件发送到业务服务器,再通过业务服务器将文件上传到OSS对象存储服务器当中。

起初觉得是没问题的,但是在使用的过程中会发现上传文件的速度很慢,显然是受到业务服务器宽带的限制。为了解决这个问题我翻看了OSS的官方文档,在里面学到了不经过业务服务器的转发,而是直接让客户端和OSS服务器进行连接直接上传。下面为大家讲解一下在客户端直连OSS的操作过程。

借用阿里云的图例

image.png

企业A需首先创建RAM用户和RAM角色,并完成相关授权操作。之后,企业B向企业A申请临时访问凭证,企业A调用AssumeRole接口获取STS临时访问凭证,然后将其传递给企业B。企业B拿到该凭证后,即可将数据上传至企业A的OSS中。

前提条件: 企业A已创建Bucket。

总结

服务器代理上传和客户端直传相比,有三个缺点:
上传慢:用户数据需先上传到应用服务器,之后再上传到OSS。网络传输时间比直传到OSS多一倍。如果用户数据不通过应用服务器中转,而是直传到OSS,速度将大大提升。而且OSS采用BGP带宽,能保证各地各运营商之间的传输速度。
扩展性差:如果后续用户多了,应用服务器会成为瓶颈。
费用高:需要准备多台应用服务器。由于OSS上传流量是免费的,如果数据直传到OSS,不通过应用服务器,那么将能省下几台应用服务器。

步骤一

1.创建RAM用户

在阿里云主账户下或拥有访问控制(RAM)管理权限的RAM账号创建RAM用户。

注意:RAM用户的AccessKey Secret仅在创建时显示,后续将无法查看。因此,强烈建议及时下载包含访问密钥(AccessKey)的CSV文件,并妥善保存至本地。

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

通过主账号授予该RAM用户通过扮演角色调用STS服务的权限。

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

image.png

3.创建RAM角色

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

image.png 单击ARN右侧的复制,保存角色的ARN

image.png

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

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

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

以下示例仅供参考。您需要根据实际需求配置更细粒度的授权策略,防止出现权限过大的风险。关于更细粒度的授权策略配置详情

image.png

RAM角色所拥有的OSS权限取决于Action的配置,例如授予oss:PutObject权限,则RAM用户在扮演RAM角色时可以对指定Bucket执行简单上传、表单上传、追加上传、分片上传、断点续传上传等操作。更多信息,请参见OSS Action说明

创建完成后如下如所示

image.png

在这之后,给RAM角色coludapi授予自定义权限策略

image.png

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服务接入点地址信息,请参见服务接入点

配置文件

  oss:
    access-key: LTAxxxxxxxxxAQ        # → accessKeyId
    secret-key: Pgxxxxxxxxxxxxxxxkx6  # → accessKeySecret
    role-arn: acs:ram::19266xxx4109:role/clouapi # → roleArn
    role-session-name: clouapi                   # → roleSessionName
    expire: 3600                                # → durationSeconds
    region: cn-hangzhou                         # → regionId

依赖

<dependency>
    <groupId>com.aliyun.oss</groupId>
    <artifactId>aliyun-sdk-oss</artifactId>
    <version>3.17.4</version>
</dependency>

代码实现:(企业B)

  public CredentialsToken getCredentials() {
      // 创建阿里云访问配置
      DefaultProfile profile = DefaultProfile.getProfile(
          OssConfiguration.region,      // cn-hangzhou
          OssConfiguration.accessKey,   // RAM用户的 
          OssConfiguration.secretKey);  // RAM用户的

      IAcsClient client = new DefaultAcsClient(profile);

      // 构造角色扮演请求
      AssumeRoleRequest request = new AssumeRoleRequest();
      request.setDurationSeconds(OssConfiguration.expire);      // 3600
      request.setRoleArn(OssConfiguration.roleArn);            // clouapi角色
      request.setRoleSessionName(OssConfiguration.roleSessionName); // clouapi

      // 获取临时凭证
      AssumeRoleResponse.Credentials response = client.getAcsResponse(request).getCredentials();

      // 返回包装后的凭证对象
      return new CredentialsToken(
          response.getAccessKeyId(),     // 临时AccessKeyId
          response.getAccessKeySecret(), // 临时AccessKeySecret
          response.getSecurityToken(),   // SecurityToken
          OssConfiguration.expire);      // 有效期
  }

将应用服务器获取到的STS临时访问凭证credentials传递给前端,前端通过解析credentials即可获得相应的凭证,从而通过凭证创建OSSClient并上传文件。

安全优势

  1. 临时性:凭证有时间限制,降低泄露风险
  2. 最小权限:只授予必要的操作权限
  3. 可审计:通过roleSessionName可以追踪使用情况
  4. 无需存储:不需要在客户端存储长期密钥

我在项目中通过重写大疆的一个抽象类AbstractMediaService,使得可以临时对我的oss进行访问 这些临时凭证主要用于:

  • KMZ文件上传下载
  • DJI Pilot设备文件传输
  • 媒体文件管理
  • 生成预签名URL
@Service
public class StorageServiceImpl extends AbstractMediaService  implements IStorageService{
/**
 * 获取STS临时凭证
 * 用于DJI Pilot上传媒体和航线文件的临时访问权限
 * @return 包含OSS访问信息和临时凭证的响应对象
 */
@Override
public StsCredentialsResponse getSTSCredentials() {
    return new StsCredentialsResponse()
            // 设置OSS访问端点
            .setEndpoint(OssConfiguration.endpoint)
            // 设置存储桶名称
            .setBucket(OssConfiguration.bucket)
            // 设置临时凭证信息
            .setCredentials(ossService.getCredentials())
            // 设置OSS服务提供商类型
            .setProvider(OssConfiguration.provider)
            // 设置对象键前缀(文件存储目录)
            .setObjectKeyPrefix(OssConfiguration.objectDirPrefix)
            // 设置区域信息
            .setRegion(OssConfiguration.region);
            }
}

参考:

OSS Java SDK V1_对象存储(OSS)-阿里云帮助中心

使用STS临时访问凭证访问OSS_对象存储(OSS)-阿里云帮助中心