AWS 资源授权(Java)-获取S3上传token

长孙嘉容
2023-12-01

目的

最近小编所在公司,项目要迁移到海外,很多之前国内使用的云服务(阿里云,百度云,腾讯云) 要更好成amazon。
aws的文档真的是一言难尽,所以小编整理了一些 aws 使用场景,方便大家参考和cv。

AWS 资源授权

资源授权以S3为例

场景

前端需要将图片上传的S3存储桶中,肯定不能直接给前端一对accessKey 和 secretKey 。
所以后端需要提供一个 有过期时间的S3存储桶的token,前端拿到这个token 作为上传凭证。

详情

  1. 引包
    使用v2版本
 </dependencyManagement>
		</dependencies>
             <dependency>
                <groupId>software.amazon.awssdk</groupId>
                <artifactId>bom</artifactId>
                <version>2.16.60</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
     <dependencies>
        <dependency>
            <groupId>software.amazon.awssdk</groupId>
            <artifactId>sts</artifactId>
        </dependency>
        <dependency>
            <groupId>software.amazon.awssdk</groupId>
            <artifactId>s3</artifactId>
        </dependency>
    </dependencies>
  1. 配置类
    前提需要有一对一对accessKey 和 secretKey ,并且该用户需要拥有sts:GetFederationToken 这个策略。
    上代码:
/**
 * @Author 
 * @Date: 2022/05/13/ 14:58
 * @Description
 */
@Data
@Service
@Configuration
public class AwsConfig {
    @Value("${aws.accessKey:}")
    private String accessKey;
    @Value("${aws.secretKey:}")
    private String secretKey;
    @Value("${aws.s3.env:}")
    private String env;
    @Value("${aws.s3.localRecord.region:}")
    private String localRecordRegion;
    @Value("${aws.s3.localRecord.bucket:}")
    private String localRecordBucket;
    @Value("${aws.s3.localRecord.durationSeconds:}")
    private Integer localRecordDurationSeconds;
    @Value("${aws.s3.localRecord.tempUserName:localRecordTemp}")
    private String localRecordTempUserName;
    @Value("${aws.s3.localRecord.host:}")
    private String localRecordHost;
    @Value("#{'${aws.sts.localRecord.action:}'.split(',')}")
    private List<String> localRecordStsAction;

    @Bean
    public StsClient stsClient() {
        AwsBasicCredentials awsCreds = AwsBasicCredentials.create(this.accessKey, this.secretKey);
        return StsClient.builder().credentialsProvider(StaticCredentialsProvider.create(awsCreds))
            .region(Region.of(this.localRecordRegion)).build();
    }
}

  1. Controller接口
@Slf4j
@Controller
@RequestMapping("/data")
public class FileController extends DataBaseController {

    @Resource
    private StsClient stsClient;
    @Autowired
    private AwsConfig awsConfig;
    @Autowired
    private RedisService redisService;

    @GetMapping("/local_record/s3_token")
    @ResponseBody
    public ResponseEntity<Response<LocalRecordUploadTokenVo>> getS3UploadToken(HttpServletRequest request) {
        Response<LocalRecordUploadTokenVo> response = new Response<>();
        HttpHeaders headers = new HttpHeaders();
        headers.setAccessControlAllowOrigin("*");
        LocalRecordUploadTokenVo uploadTokenCacheVo =
            redisService.get(RedisConstant.LOCAL_RECORD_S3_TOKEN, LocalRecordUploadTokenVo.class);
        if (uploadTokenCacheVo != null
            && uploadTokenCacheVo.getExpiredTime() > System.currentTimeMillis() / 1000 + 1200) {
            response.success().data(uploadTokenCacheVo);
            return new ResponseEntity<>(response, headers, HttpStatus.OK);
        }
        String policy = String.format(
            "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Action\":%s,\"Resource\":\"arn:aws:s3:::%s/%s/*\"}]}",
            awsConfig.getLocalRecordStsAction(), awsConfig.getLocalRecordBucket(), awsConfig.getEnv());
        GetFederationTokenRequest build =
            GetFederationTokenRequest.builder().name(awsConfig.getLocalRecordTempUserName()).policy(policy)
                .durationSeconds(awsConfig.getLocalRecordDurationSeconds()).build();
        LocalRecordUploadTokenVo tokenVo;
        try {
            GetFederationTokenResponse federationToken = stsClient.getFederationToken(build);
            Credentials credentials = federationToken.credentials();
            tokenVo = new LocalRecordUploadTokenVo(federationToken.responseMetadata().requestId(), credentials);
            tokenVo.setBucket(awsConfig.getLocalRecordBucket());
            tokenVo.setRegion(awsConfig.getLocalRecordRegion());
            response.success().data(tokenVo);
            redisService.set(RedisConstant.LOCAL_RECORD_S3_TOKEN, tokenVo, 600L);
        } catch (Exception e) {
            log.error("FileController::getS3UploadToken 获取上传签名失败", e);
            response.success().message(e.getMessage());
        }
        return new ResponseEntity<>(response, headers, HttpStatus.OK);
    }
   }
 这里加了redis缓存
 awsConfig.getLocalRecordStsAction() 的值为"s3:GetObject","s3:PutObject","s3:PutObjectAcl"
 awsConfig.getEnv() 为环境类型 如qa online
 代码仅供参考
 类似资料: