使用STS临时访问凭证访问OSS-实践记录

本文档详细介绍了如何使用阿里云RAM用户和STS服务创建临时访问凭证,以安全地访问和上传文件到OSS。首先创建RAM用户并保存访问密钥,然后为用户授权请求AssumeRole的权限。接着创建角色并定义上传文件的权限策略。通过STS服务获取临时访问凭证,并在客户端使用这些凭证初始化OSSClient以上传文件。此外,还展示了如何使用签名URL进行临时授权访问。整个过程确保了资源访问的安全性,避免了长期密钥的暴露。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.创建RAM用户

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

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

创建用户,保存访问密钥(AccessKey ID 和 AccessKey Secret);

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

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

已创建RAM用户右侧对应的添加权限

3.创建用于获取临时访问凭证的角色

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

以 RamOssTest 为名,进行说明;

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

  1. 创建上传文件的自定义权限策略 -以 RamTestPolicy为名,进行说明;

    {
      "Version": "1",
      "Statement": [
        {
          "Effect": "Allow",
          "Action": [
            "oss:PutObject"
          ],
          "Resource": [
            "acs:oss:*:*:examplebucket/exampledir",
            "acs:oss:*:*:examplebucket/exampledir/*"
          ]
        }
      ]
    }
    
  2. 为RAM角色 RamOssTest 授予自定义权限策略;

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

5.获取临时访问凭证

AssumeRole ;

Node.js 授权访问

// 通过STS服务生成临时访问凭证
const OSS = require('ali-oss');

// 阿里云账号AccessKey拥有所有API的访问权限,风险很高;
// 强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户;
const sts = new OSS.STS({
  accessKeyId: 'accessKeyId',
  accessKeySecret: 'accessKeySecret'
});

// 参考以下示例代码,具体参数说明详见下列链接:
// roleArn: 格式为acs:ram::$accountID:role/$roleName;
// policy: 为步骤4填写的权限策略;
// sessionName: 用户自定义参数。此参数用来区分不同的令牌,可用于用户级别的访问审计;
// https://help.aliyun.com/document_detail/28763.htm
// sts.assumeRole('roleArn', 'policy', 'expiration', 'sessionName').then((result) => {
//   console.log(result);
// }).catch((err) => {
//   console.log(err);
// });

sts.assumeRole('acs:ram::123456789012****:role/adminrole', {
  "Version": "1",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "oss:PutObject"
      ],
      "Resource": [
        "acs:oss:*:*:examplebucket/exampledir",
        "acs:oss:*:*:examplebucket/exampledir/*"
      ]
    }
  ]
}, '3600', 'adminrole').then((result) => {
  // SecretCode - example:
  // {
  //   SecurityToken: 'SecurityToken',
  //   AccessKeyId: 'STS.XXXXXXX',
  //   AccessKeySecret: 'AccessKeySecret',
  //   Expiration: '2020-03-12T03:16:01Z'
  // }
  console.log(result.credentials);
}).catch((err) => {
  console.log(err);
});


// 在客户端使用临时访问凭证初始化OSSClient,用于临时授权访问OSS资源
const axios = require("axios");
const OSS = require("ali-oss");

// 在客户端使用临时访问凭证初始化OSS客户端,用于临时授权访问OSS资源。
const getToken = async () => {
  // 设置客户端请求访问凭证的地址。
  await axios.get("https:/xxx/sts").then((token) => {
    const client = new OSS({
      // 以华东1(杭州)为例,yourRegion填写为oss-cn-hangzhou
      region: 'yourRegion',
      accessKeyId: token.AccessKeyId,
      accessKeySecret: token.AccessKeySecret,
      stsToken: token.SecurityToken,
      // 填写Bucket名称,例如examplebucket
      bucket: "examplebucket",
      // 刷新临时访问凭证
      refreshSTSToken: async () => {      
        const refreshToken = await axios.get("https://xxx/sts");
        return {
          accessKeyId: refreshToken.AccessKeyId,
          accessKeySecret: refreshToken.AccessKeySecret,
          stsToken: refreshToken.SecurityToken,
        };
      },
    });
  });
};

6.使用临时访问凭证上传文件至OSS

微信小程序直传实践

// 使用阿里云 OSS-SDK 上传
const OSS = require('ali-oss');

// 填写步骤5获取的临时访问密钥(AccessKey ID、AccessKey Secret 和 SecurityToken)
const client = new OSS({
  region: 'oss-cn-hangzhou',
  accessKeyId: 'STS.XXXXXXX',
  accessKeySecret: 'AccessKeySecret',
  bucket: 'examplebucket',
  stsToken: 'SecurityToken'
});

const data = document.getElementById("file").files[0];

const result = await client.put(
  "application/x-oss-forbid-overwrite.png",
  data
  // {headers}
);


// 使用 axios、wx.uploadFile 等工具上传
// https://help.aliyun.com/document_detail/92883.html
import { Base64 } from 'js-base64';

const policyText = {
  // 设置该Policy的失效时间,超过这个失效时间之后,就没有办法通过这个policy上传文件
  expiration: `${new Date(timestamp).toISOString()}`,
  conditions: [
    // 限制上传大小
    ["content-length-range", 0, 1024 * 1024 * 1024],
  ],
};
const policy = Base64.encode(JSON.stringify(policyText));
// 填写步骤5获取的临时访问密钥(AccessKey Secret)
const Signature = crypto.enc.Base64.stringify(crypto.HmacSHA1(policy, "accessKeySecret"));

// 服务端签名直传并设置上传回调,该参数可选
// https://help.aliyun.com/document_detail/31927.html?spm=a2c4g.11186623.6.1388.24906e28BwjPD3
const callback = {
  callbackUrl: 'https://tuanzi.test.com/callback',
  callbackBody:
    "filename=${object}&size=${size}&mimeType=${mimeType}&height=${imageInfo.height}&width=${imageInfo.width}",
  callbackBodyType: "application/x-www-form-urlencoded",
}
const CallbackUrls = Buffer.from(JSON.stringify(callback)).toString("base64")

// 填写步骤5获取的临时访问密钥(AccessKey ID 和 SecurityToken)
function fileCreate (file) {
  const uploadData = new FormData();
  uploadData.append("OSSAccessKeyId", 'STS.XXXXXXX');
  uploadData.append("key", 'application/${filename}');
  uploadData.append("policy", policy);
  uploadData.append("success_action_status", 200);
  uploadData.append("name", file.name);
  // 使用STS签名时必传
  uploadData.append("x-oss-security-token", "securityToken");
  uploadData.append("Signature", Signature);
  // uploadData.append("callback", CallbackUrls);

  uploadData.append("file", file);

  return uploadData;
}

const file = document.getElementById("file").files[0];
const uploadData = fileCreate(file);
axios({
  url: 'http://examplebucket.oss-cn-hangzhou.aliyuncs.com',
  method: 'post',
  data: uploadData,
  headers: { 'Content-Type': 'multipart/form-data' }
}).then(r => console.log(r));

7.使用签名URL进行临时授权

可以将生成的签名URL提供给访客进行临时访问;

生成签名URL时,您可以通过指定URL的过期时间来限制访客的访问时长。签名URL的默认过期时间为3600秒,最大值为32400秒;

const OSS = require('ali-oss');

// 阿里云账号AccessKey拥有所有API的访问权限,风险很高;
// 强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户;
const client = new OSS({
  region: 'oss-cn-hangzhou',
  accessKeyId: 'accessKeyId',
  accessKeySecret: 'accessKeySecret',
  bucket: 'examplebucket',
});
// 用于生成对应签名URL来上传和下载文件
// const url = client.signatureUrl('pathname/2Q2tTXZ5JRHb72.png');

// 生成带图片处理参数的签名URL
const url = client.signatureUrl('pathname/2Q2tTXZ5JRHb72.png', { 
  // 设置过期时间,默认值为1800秒。
  expires: 3600, 
  // 设置图片处理参数。
  process: 'image/resize,w_200' 
});

// http://examplebucket.region.aliyuncs.com/pathname/filename.png?OSSAccessKeyId=OSSAccessKeyId&Expires=1647075144&Signature=Signature
console.log(url);
### 后端处理文件上传的最佳实践 #### 文件上传的核心流程 文件上传通常涉及客户端发送请求以及后端接收并存储文件的过程。为了确保高效性和安全性,以下是几个核心要点: 1. **使用临时令牌进行权限控制** 对于敏感操作(如文件上传),建议采用临时授权机制来增强安全性和灵活性。例如,在阿里云OSS中可以通过STS服务生成短期有效的访问凭证[^2]。 2. **分片上传优化大文件传输效率** 针对较大的文件,推荐实施分片上传策略以降低单次请求失败的风险,并提高网络波动下的稳定性[^1]。 3. **监控与反馈实时状态更新** 提供清晰的状态报告有助于改善用户体验;这包括但不限于初始化确认、进度条显示直至最终完成通知等功能模块设计思路。 4. **错误处理及日志记录完善异常管理方案** 建立健全的日志体系对于排查问题至关重要,同时合理定义各类可能发生的错误类型及其对应的解决方案也是不可或缺的一部分内容之一[^3]。 #### PHP 实现示例 下面展示了一个简单的PHP脚本用于演示基本的文件接收逻辑: ```php <?php if ($_SERVER['REQUEST_METHOD'] === 'POST') { $target_dir = "uploads/"; $target_file = $target_dir . basename($_FILES["fileToUpload"]["name"]); // Check if file already exists if (file_exists($target_file)) { echo json_encode(["status"=>"error", "message"=> "File already exists."]); exit; } // Validate and move uploaded file if (move_uploaded_file($_FILES["fileToUpload"]["tmp_name"], $target_file)) { echo json_encode(["status"=>"success", "message"=> "The file ". htmlspecialchars(basename($_FILES["fileToUpload"]["name"])). " has been uploaded."]); } else { echo json_encode(["status"=>"error", "message"=> "Sorry, there was an error uploading your file."]); } } ?> ``` #### Python Flask 示例 这里提供了一种利用Flask框架构建RESTful API的方式来进行文件上传的操作方法说明如下所示: ```python from flask import Flask, request, jsonify import os app = Flask(__name__) UPLOAD_FOLDER = './uploads' os.makedirs(UPLOAD_FOLDER, exist_ok=True) @app.route('/upload', methods=['POST']) def upload_file(): if 'file' not in request.files: return jsonify({"status": "error", "message": "No file part"}), 400 file = request.files['file'] if file.filename == '': return jsonify({"status": "error", "message": "No selected file"}), 400 try: filepath = os.path.join(UPLOAD_FOLDER, file.filename) file.save(filepath) return jsonify({"status": "success", "message": f"File {file.filename} saved successfully!"}) except Exception as e: return jsonify({"status": "error", "message": str(e)}), 500 if __name__ == '__main__': app.run(debug=True) ``` ### 注意事项 - 确保服务器配置允许适当大小范围内的文件上传。 - 考虑设置合理的超时时间防止长时间占用资源。 - 加密通信渠道保护数据隐私安全[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值