【Spring Cloud】Spring Cloud Alibaba OSS

OSS 简介

对象存储服务(Object Storage Service,OSS)用于是一种海量、安全、低成本、高可靠的云存储服务,适合存放任意类型的文件。容量和处理能力弹性扩展,多种存储类型供选择,全面优化存储成本。

阿里巴巴提供了云对象存储服务 Alibaba OSS,可以将对象数据存储在云端,在本地数据库仅存储 URL。本文章将介绍如何在项目中使用 Alibaba OSS。

创建 Bucket

创建自己的对象存储 Bucket:yunmall-project

image-20211227212122593

设置读写权限为公共读

image-20220101152432522

配置第三方服务

本节展示如何在 Spring Cloud 项目中配置 OSS。具体项目见文章【Project】云商城

  1. 导入阿里云 OSS 的场景启动器依赖:
1
2
3
4
5
6
<!-- 阿里云OSS,对于某些SpringBoot版本的场景启动器,需要特别指定版本,否则会无法导入-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alicloud-oss</artifactId>
<version>2.2.0.RELEASE</version>
</dependency>
  1. 配置文件:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
server:
port: 30000

spring:
cloud:
nacos:
# 服务注册中心
discovery:
server-addr: localhost:8848
# 阿里云OSS配置
alicloud:
# 自己阿里云账号下的RAM用户的访问密码,注意不能使用自己阿里云账号的访问密码!
access-key:
secret-key:
oss:
endpoint: oss-cn-hangzhou.aliyuncs.com
bucket: yunmall-project

# endpoint填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。
#
  1. 在网关中配置第三方服务的路由规则:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
spring:
application:
name: yunmall-gateway
cloud:
nacos:
# 注册中心
discovery:
server-addr: localhost:8848
gateway:
routes:
# 第三方服务的路由规则
- id: third-party-route
uri: lb://yunmall-third-party
predicates:
- Path=/api/third-party/**
filters:
- RewritePath=/api/third-party/(?<segment>.*), /$\{segment}

注意:阿里云账号 AccessKey 拥有所有 API 的访问权限,风险很高。强烈建议您创建并使用 RAM 用户进行API访问或日常运维,请登录 RAM 控制台创建 RAM 用户。


RAM 用户是 RAM 中的一种身份,对应某一个操作实体(运维操作人员或应用程序)。通过创建新的RAM用户并授权,RAM用户便可以访问相关资源。

创建步骤:

  1. 使用阿里云账号登录 RAM控制台
  2. 在左侧导航栏,选择身份管理 > 用户
  3. 用户页面,单击创建用户
  4. 创建用户页面的用户账号信息区域,输入登录名称显示名称
    说明 单击添加用户,可一次性创建多个 RAM 用户。
  5. 访问方式区域,选择访问方式。
    • 控制台访问:设置控制台登录密码、重置密码策略和多因素认证策略。
    • OpenAPI调用访问:自动为 RAM 用户生成访问密钥(AccessKey),支持通过API或其他开发工具访问阿里云。
  6. 单击确定

  1. 在 Controller 层配置,向 OSS 发出请求或许许可签名:
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
56
57
58
59
60
61
62
63
/**
* @author yuyun zhao
* @date 2021/12/27 20:53
*/
@RestController
public class OssController {
@Autowired
OSS ossClient;

@Value("${spring.cloud.alicloud.oss.endpoint}")
private String endpoint;

@Value("${spring.cloud.alicloud.oss.bucket}")
private String bucket;

@Value("${spring.cloud.alicloud.access-key}")
private String accessId;

/**
* 签名方法
* @return 返回给前端JSON字符串,注意必须封装成R对象,因为和前端的通讯协议里,都是从response.data中获取数据
*/
@RequestMapping("/oss/policy")
public R policy() {
String host = "https://" + bucket + "." + endpoint; // host的格式为 bucketname.endpoint
// callbackUrl为上传回调服务器的URL,请将下面的IP和Port配置为您自己的真实信息。
// String callbackUrl = "http://88.88.88.88:8888";
String date = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
// 用户上传文件时指定的前缀。
String dir = date + "/";

Map<String, String> respMap = null;
try {
long expireTime = 30;
long expireEndTime = System.currentTimeMillis() + expireTime * 1000;
Date expiration = new Date(expireEndTime);
// PostObject请求最大可支持的文件大小为5GB,即CONTENT_LENGTH_RANGE为5*1024*1024*1024。
PolicyConditions policyConds = new PolicyConditions();
policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 1048576000);
policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, dir);

String postPolicy = ossClient.generatePostPolicy(expiration, policyConds);
byte[] binaryData = postPolicy.getBytes("utf-8");
String encodedPolicy = BinaryUtil.toBase64String(binaryData);
String postSignature = ossClient.calculatePostSignature(postPolicy);

respMap = new LinkedHashMap<String, String>();
respMap.put("accessid", accessId);
respMap.put("policy", encodedPolicy);
respMap.put("signature", postSignature);
respMap.put("dir", dir);
respMap.put("host", host);
respMap.put("expire", String.valueOf(expireEndTime / 1000));
// respMap.put("expire", formatISO8601Date(expiration));
} catch (Exception e) {
// Assert.fail(e.getMessage());
System.out.println(e.getMessage());
} finally {
ossClient.shutdown();
}
return R.ok().put("data", respMap);
}
}

单独使用阿里云 OSS 的配置参考阿里云官方文档:https://help.aliyun.com/document_detail/84781.html

  1. 在前端工程中导入封装好的上传组件:

image-20211227211934007

在其中修改地址为自己的 Bucket 外网访问域名:action="http://yunmall-project.oss-cn-hangzhou.aliyuncs.com"。这样前端在收到第三方服务发来的许可签名后,就可以使用该签名里的访问密码信息向配置的 Bucket 中上传图片数据。

  1. 测试:观察前端发送的请求,分别为:
  • 去后端第三方服务要签名数据
  • 拿到签名数据后再去阿里云提交请求获取图片数据

image-20211227220201294

其中,请求发送了两次的原因是第一次是 OPTION 预检请求。

跨域问题

在前端项目发出请求试图访问阿里云的 OSS 服务器时,同样会出现跨域问题。

image-20211227214629342

image-20211227214728392

image-20211227215530358