AWS STS凭证上传过期问题:如何中途更新凭证或自动重试?
解决AWS SDK v2大文件上传STS凭证过期问题
方案一:自定义自动刷新的STS凭证提供者
AWS SDK v2支持自定义Credentials类,通过实现refresh方法,让SDK在凭证过期时自动获取新凭证,无需手动干预。
代码实现
const AWS = require('aws-sdk'); class CustomSTSCredentials extends AWS.Credentials { constructor(initialCreds) { // 初始化初始凭证 super(initialCreds.aws_access_key_id, initialCreds.aws_secret_access_key, initialCreds.aws_session_token); // 将过期时间转为Date对象 this.expires = new Date(initialCreds.expires_at); } // 自定义凭证刷新逻辑 async refresh(callback) { try { // 调用你的服务器接口获取新的STS凭证 const newCreds = await fetch('/your-server-sts-api', { method: 'POST', body: JSON.stringify({ bucket_name: '你的存储桶名', basepath: '文件上传路径前缀' }) }).then(res => res.json()); // 更新凭证信息 this.accessKeyId = newCreds.aws_access_key_id; this.secretAccessKey = newCreds.aws_secret_access_key; this.sessionToken = newCreds.aws_session_token; this.expires = new Date(newCreds.expires_at); callback(null); } catch (err) { callback(err); } } } // 初始化S3客户端,使用自定义凭证 const s3 = new AWS.S3({ region: bucket_region, credentials: new CustomSTSCredentials(initialStsCredentials), correctClockSkew: true }); // 正常执行上传 s3.upload({ Bucket: bucket_name, Key: `${basepath}/目标文件名`, Body: 大文件流, ACL: acl }, (err, data) => { if (err) { console.error('上传失败:', err); } else { console.log('上传成功:', data.Location); } });
原理说明
SDK会自动监控凭证的过期时间,当凭证即将过期或已过期时,自动调用refresh方法获取新凭证,然后继续分块上传的后续请求,全程无需手动介入。
方案二:捕获过期错误后手动更新凭证并重试
如果自定义凭证提供者不符合你的场景,可以捕获ExpiredToken错误,手动获取新凭证后重试上传。
代码实现
const AWS = require('aws-sdk'); let currentStsCreds = initialStsCredentials; const s3 = new AWS.S3({ region: bucket_region, correctClockSkew: true }); // 封装带重试逻辑的上传函数 async function uploadWithRetry(uploadParams, retryCount = 0) { try { // 每次重试前更新S3客户端的凭证 s3.config.update({ accessKeyId: currentStsCreds.aws_access_key_id, secretAccessKey: currentStsCreds.aws_secret_access_key, sessionToken: currentStsCreds.aws_session_token }); const result = await s3.upload(uploadParams).promise(); return result; } catch (err) { // 判断是否为凭证过期错误,且重试次数未超限 if (err.code === 'ExpiredToken' && retryCount < 3) { // 获取新的STS凭证 currentStsCreds = await fetch('/your-server-sts-api', { method: 'POST', body: JSON.stringify({ bucket_name: uploadParams.Bucket, basepath: uploadParams.Key.split('/').slice(0, -1).join('/') }) }).then(res => res.json()); // 重试上传 return uploadWithRetry(uploadParams, retryCount + 1); } // 非过期错误或重试超限,抛出原错误 throw err; } } // 调用上传函数 uploadWithRetry({ Bucket: bucket_name, Key: `${basepath}/目标文件名`, Body: 大文件流, ACL: acl }) .then(data => console.log('上传成功:', data.Location)) .catch(err => console.error('上传失败:', err));
注意事项
- 需限制重试次数,避免因服务器无法返回有效凭证导致无限循环。
- 确保新获取的STS凭证权限与原凭证一致,且针对同一存储桶和路径。
内容的提问来源于stack exchange,提问作者transient eternity
相关产品推荐
相关产品推荐

