赞
踩
采用JavaScript客户端直接签名时,AccessKeyID和AcessKeySecret会暴露在前端页面,因此存在严重的安全隐患。因此,OSS提供了服务端签名后直传的方案。
服务端签名后直传的原理如下:
1.用户发送上传Policy请求到应用服务器。
2.应用服务器返回上传Policy和签名给用户。
3.用户直接上传数据到OSS。
本示例中,Web端向服务端请求签名,然后直接上传,不会对服务端产生压力,而且安全可靠。但本示例中的服务端无法实时了解用户上传了多少文件,上传了什么文件。如果想实时了解用户上传了什么文件,可以采用服务端签名直传并设置上传回调。详见下片文章阿里oss服务端签名直传并设置上传回调。
官方文档地址:服务端签名后直传
Endpoint:访问域名,通过该域名可以访问OSS服务的API,进行文件上传、下载等操作。
Bucket:存储空间,是存储对象的容器,所有存储对象都必须隶属于某个存储空间。
Object:对象,对象是 OSS 存储数据的基本单元,也被称为 OSS 的文件。
AccessKey:访问密钥,指的是访问身份验证中用到的 AccessKeyId 和 AccessKeySecret。
之前有一篇文章已经介绍了各个参数的位置。如有不知道的,请看这篇springboot整合oss实现文件的上传,查看,删除,下载
在pom.xml中添加相关依赖
<!-- OSS SDK 相关依赖 -->
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>2.5.0</version>
</dependency>
修改SpringBoot配置文件
server:
port: 80
# OSS相关配置信息
aliyun:
oss:
endpoint: endpoint # oss对外服务的访问域名
accessKeyId: accessKeyId # 访问身份验证中用到用户标识
accessKeySecret: accessKeySecret # 用户用于加密签名字符串和oss用来验证签名字符串的密钥
bucketName: tuanzi-ne # oss的存储空间
policy:
expire: 300 # 签名有效期(S)
maxSize: 10 # 上传文件大小(M)
dir:
prefix: tuanzi/images/ # 上传文件夹路径前缀
添加OSS的相关Java配置
用于配置OSS的连接客户端OSSClient。
package com.tuanzi.config; import com.aliyun.oss.OSSClient; import lombok.Data; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * oss配置文件 * @auther 团子 * @date 2019-07-31 10:03 */ @Configuration @Data public class OssConfig { @Value("${aliyun.oss.endpoint}") private String ALIYUN_OSS_ENDPOINT; @Value("${aliyun.oss.accessKeyId}") private String ALIYUN_OSS_ACCESSKEYID; @Value("${aliyun.oss.accessKeySecret}") private String ALIYUN_OSS_ACCESSKEYSECRET; @Bean public OSSClient ossClient(){ return new OSSClient(ALIYUN_OSS_ENDPOINT, ALIYUN_OSS_ACCESSKEYID, ALIYUN_OSS_ACCESSKEYSECRET); } }
添加OSS上传策略封装对象OssPolicyResult
前端直接上传文件时所需参数,从后端返回过来。
package com.tuanzi.dto; import io.swagger.annotations.ApiModelProperty; import lombok.Data; /** * 获取OSS上传文件授权返回结果 * @auther 团子 * @date 2019-07-31 11:31 */ @Data public class OssPolicyResult { @ApiModelProperty("访问身份验证中用到用户标识") private String accessKeyId; @ApiModelProperty("用户表单上传的策略,经过base64编码过的字符串") private String policy; @ApiModelProperty("对policy签名后的字符串") private String signature; @ApiModelProperty("上传文件夹路径前缀") private String dir; @ApiModelProperty("oss对外服务的访问域名") private String host; }
添加OssController定义接口
/** * Oss相关操作接口 * @auther 团子 * @date 2019-07-31 11:31 */ @Controller @Api(tags = "OssController", description = "Oss管理") @RequestMapping("/aliyun/oss") public class OssController { public static final Logger logger = LoggerFactory.getLogger(OssController.class); @Autowired private OssServiceImpl ossService; @ApiOperation(value = "oss上传签名生成") @RequestMapping(value = "/policy", method = RequestMethod.GET) @ResponseBody public CommonResult<OssPolicyResult> policy() { logger.info("policy --------------> start"); OssPolicyResult result = ossService.policy(); logger.info("policy --------------> end"); return CommonResult.success(result); } }
添加OSS业务接口OssService
/**
* oss上传管理Service
* @auther 团子
* @date 2019-07-31 11:31
*/
public interface OssService {
/**
* oss上传策略生成
*/
OssPolicyResult policy();
}
添加OSS业务接口OssService的实现类OssServiceImpl
private static final Logger LOGGER = LoggerFactory.getLogger(OssServiceImpl.class); @Value("${aliyun.oss.policy.expire}") private int ALIYUN_OSS_EXPIRE; @Value("${aliyun.oss.maxSize}") private int ALIYUN_OSS_MAX_SIZE; @Value("${aliyun.oss.bucketName}") private String ALIYUN_OSS_BUCKET_NAME; @Value("${aliyun.oss.endpoint}") private String ALIYUN_OSS_ENDPOINT; @Value("${aliyun.oss.dir.prefix}") private String ALIYUN_OSS_DIR_PREFIX; @Autowired private OSSClient ossClient; /** * 签名生成 */ @Override public OssPolicyResult policy() { OssPolicyResult result = new OssPolicyResult(); // 存储目录 SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd"); String dir = ALIYUN_OSS_DIR_PREFIX+sdf.format(new Date()); // 签名有效期 long expireEndTime = System.currentTimeMillis() + ALIYUN_OSS_EXPIRE * 1000; Date expiration = new Date(expireEndTime); // 文件大小 long maxSize = ALIYUN_OSS_MAX_SIZE * 1024 * 1024; // 提交节点 String action = "http://" + ALIYUN_OSS_BUCKET_NAME + "." + ALIYUN_OSS_ENDPOINT; try { PolicyConditions policyConds = new PolicyConditions(); policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, maxSize); policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, dir); String postPolicy = ossClient.generatePostPolicy(expiration, policyConds); byte[] binaryData = postPolicy.getBytes("utf-8"); String policy = BinaryUtil.toBase64String(binaryData); String signature = ossClient.calculatePostSignature(postPolicy); result.setAccessKeyId(ossClient.getCredentialsProvider().getCredentials().getAccessKeyId()); result.setPolicy(policy); result.setSignature(signature); result.setDir(dir); result.setHost(action); } catch (Exception e) { LOGGER.error("签名生成失败", e); } return result; }
这样我们就全写完了。我们来进行接口测试!
这里我利用postman进行演示
会调用两次请求,第一次访问本地接口获取上传的策略
第二次调用oss服务 的接口进行文件上传
我们再来看看oss管理控制台
完整源码地址:阿里oss服务端签名后直传
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。