获取并生成 Aliyun STS 签名 URL 访问 OSS

本文最后更新于 2024年11月5日 晚上

此文章是在搭建 cn 站 v2 的过程中的一个小弯路

如果使用服务器连接 OSS,不需要 STS 授权,直接 IP 授权即可。

此方法适用于给用户临时授权,

使用 Spring Boot 搭建授权服务

为了方便后续拆分,以及调整,此处将 博客页面和图片 的授权分别放置于不同的模块中。

关于授权的相关概念

获取临时访问安全令牌 STS

  1. 前往 RAM 访问控制 - 用户: https://ram.console.aliyun.com/users
  2. 创建用户 ZEO-OSS-USER 授权 STS 服务,OSS 管理权限
  3. 创建用户后,分别进入用户详情页,创建 AccessKey,记录 ID 和 key
  4. 前往 RAM 访问控制 - 角色:https://ram.console.aliyun.com/roles
  5. 创建角色 ZEO-OSS-Role 授权 STS 服务
  6. 进入角色详情页,记录角色名称ARN
  7. 前往 AssumeRole_安全令牌_API调试-阿里云OpenAPI开发者门户: https://next.api.aliyun.com/api/Sts/2015-04-01/AssumeRole
  8. 填入必要参数,并复制生成的代码以及SDK依赖
  9. 改编获取到的代码示例,我这儿将它改编成了一个工具类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
package com.cc01cc.blog.Utils;

import com.aliyun.sts20150401.models.AssumeRoleResponse;
import com.aliyun.tea.TeaException;

/**
* @author cc01cc
*
* 代码改编自 阿里云 OpenAI <https://next.api.aliyun.com/api/Sts/2015-04-01/AssumeRole>
*/
public class AliyunStsUtils {
/**
* 使用AK&SK初始化账号Client
*
* @param accessKeyId
* @param accessKeySecret
* @return Client
* @throws Exception
*/
public static com.aliyun.sts20150401.Client createClient(String accessKeyId, String accessKeySecret)
throws Exception {
com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config()
// 必填,您的 AccessKey ID
.setAccessKeyId(accessKeyId)
// 必填,您的 AccessKey Secret
.setAccessKeySecret(accessKeySecret);
// 访问的域名
config.endpoint = "sts.cn-hangzhou.aliyuncs.com";
return new com.aliyun.sts20150401.Client(config);
}

public static AssumeRoleResponse getSts(String accessKeyId, String accessKeySecret, String roleSessionName,
String roleArn, Long durationSeconds) throws Exception {
// 工程代码泄露可能会导致AccessKey泄露,并威胁账号下所有资源的安全性。以下代码示例仅供参考,建议使用更安全的 STS
// 方式,更多鉴权访问方式请参见:https://help.aliyun.com/document_detail/378657.html
com.aliyun.sts20150401.Client client = createClient(accessKeyId, accessKeySecret);
com.aliyun.sts20150401.models.AssumeRoleRequest assumeRoleRequest = new com.aliyun.sts20150401.models.AssumeRoleRequest()
.setRoleSessionName(roleSessionName)
.setRoleArn(roleArn)
.setDurationSeconds(durationSeconds);
com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
try {
// 复制代码运行请自行打印 API 的返回值
return client.assumeRoleWithOptions(assumeRoleRequest, runtime);
} catch (TeaException error) {
// 如有需要,请打印 error
com.aliyun.teautil.Common.assertAsString(error.message);
} catch (Exception _error) {
TeaException error = new TeaException(_error.getMessage(), _error);
// 如有需要,请打印 error
com.aliyun.teautil.Common.assertAsString(error.message);
}
return null;
}
}

参考 Credentials 设置: https://help.aliyun.com/document_detail/378657.html

使用 STS 生成 签名 URL

Java授权访问: https://help.aliyun.com/document_detail/32016.htm#p-f2i-r4x-6lz

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
/**
* 代码改编自 Java授权访问:
* https://help.aliyun.com/document_detail/32016.htm#p-f2i-r4x-6lz
*
* @param endpoint
* @param accessKeyId STS 所返回的 accessKeyId,不是 ram 的 accessKeyId 下同
* @param accessKeySecret
* @param securityToken
* @param bucketName
* @param objectName
* @param durationSeconds
* @return
*/
public static URL getPresignedUrl(String endpoint, String accessKeyId, String accessKeySecret, String securityToken,
String bucketName, String objectName, Long durationSeconds) {
// 从STS服务获取临时访问凭证后,您可以通过临时访问密钥和安全令牌生成OSSClient。
// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret, securityToken);

try {
// 设置签名URL过期时间,单位为毫秒。
Date expiration = new Date(new Date().getTime() + durationSeconds * 1000);
// 生成以GET方法访问的签名URL,访客可以直接通过浏览器访问相关内容。
URL url = ossClient.generatePresignedUrl(bucketName, objectName, expiration);
System.out.println(url);
return url;
} 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());
} catch (ClientException ce) {
System.out.println("Caught an ClientException, which means the client encountered "
+ "a serious internal problem while trying to communicate with OSS, "
+ "such as not being able to access the network.");
System.out.println("Error Message:" + ce.getMessage());
} finally {
if (ossClient != null) {
ossClient.shutdown();
}
}
return null;
}

将以上的方法合并获取签名 url

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/**
* 直接通过 ram 获取 签名 url
*
* @param accessKeyId
* @param accessKeySecret
* @param roleSessionName
* @param roleArn
* @param durationSeconds
* @param endpoint
* @param bucketName
* @param objectName
* @return
*/
public static URL getPresignedUrl(String accessKeyId, String accessKeySecret, String roleSessionName,
String roleArn, Long durationSeconds, String endpoint, String bucketName, String objectName) {
AssumeRoleResponse sts;
try {
sts = getSts(accessKeyId, accessKeySecret, roleSessionName,
roleArn, durationSeconds);
AssumeRoleResponseBodyCredentials credentials = sts.getBody().getCredentials();
return getPresignedUrl(endpoint, credentials.accessKeyId, credentials.accessKeySecret,
credentials.securityToken, bucketName, objectName, durationSeconds);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}

获取并生成 Aliyun STS 签名 URL 访问 OSS
https://blog.cc01cc.cn/2023/04/02/blog-build-aliyun-sts/
作者
零一/cc01cc(zeo)
发布于
2023年4月2日
许可协议