springBoot+Vue实现阿里云OSS对象存储服务端签名客户端直传

这里写自定义目录标题

  • 使用STS临时访问凭证访问OSS
    • 一、配置RAM用户与RAM角色
    • 二、通过SpringBoot获取临时访问凭证
    • 三、前端上传文件
    • 四、客户端直传安全问题

2次传输:客户端->OSS
3次传输:客户端->服务端->OSS
虽然使用阿里云服务器传输到阿里云OSS属于内网传输有千兆带宽,但2次传输就是>3次传输,所以我考虑很久还是在自己的项目中用客户端直传方式,数据安全也有其他策略可以补救

使用STS临时访问凭证访问OSS

通过STS服务给其他用户颁发一个临时访问凭证。该用户可使用临时访问凭证在规定时间内访问您的OSS资源。临时访问凭证无需透露您的长期密钥,使您的OSS资源访问更加安全。
springBoot+Vue实现阿里云OSS对象存储服务端签名客户端直传_第1张图片

一、配置RAM用户与RAM角色

通过以下链接按步骤配置
https://help.aliyun.com/zh/oss/developer-reference/use-temporary-access-credentials-provided-by-sts-to-access-oss?spm=a2c4g.11186623.0.0.1fc27f7aX7rZHJ
注意: 配置到第四部即可,第四步的权限策略脚本中的Resource应该填写自己的bucket
“Resource”: “acs:oss:*:1021347314873735:bucketName/objectName” (其实就是访问路径,也可以是通配符 * )

	{
       "Version": "1",
       "Statement": [
           {
               "Effect": "Allow",
               "Action": "oss:PutObject",
               "Resource": "acs:oss:*:1021347314873735:*/*"      
           }
       ]
   }

配置中我们需要保存的信息:
配置成功后

二、通过SpringBoot获取临时访问凭证

  1. 在Maven工程中使用OSS Java SDK,只需在pom.xml中加入相应依赖即可。以3.15.1版本为例,在中加入如下内容:

    <dependency>
        <groupId>com.aliyun.oss</groupId>
        <artifactId>aliyun-sdk-oss</artifactId>
        <version>3.15.1</version>
    </dependency>
    //如果使用的是Java 9及以上的版本,则需要添加jaxb相关依赖。添加jaxb相关依赖示例代码如下:
    <dependency>
        <groupId>javax.xml.bind</groupId>
        <artifactId>jaxb-api</artifactId>
        <version>2.3.1</version>
    </dependency>
    <dependency>
        <groupId>javax.activation</groupId>
        <artifactId>activation</artifactId>
        <version>1.1.1</version>
    </dependency>
    <!-- no more than 2.3.3-->
    <dependency>
        <groupId>org.glassfish.jaxb</groupId>
        <artifactId>jaxb-runtime</artifactId>
        <version>2.3.3</version>
    </dependency>
    
  2. 创建oss配置类,将对应配置信息填写在application.yml文件中,当然你直接写死在代码里面也可以

    @Configuration
    @ConfigurationProperties(prefix = "alioss")
    @Data
    public class AliOssConfig {
    	 // STS接入地址,例如sts.cn-hangzhou.aliyuncs.com。
    	 String endpoint;
        // 填写步骤1生成的RAM用户访问密钥AccessKey ID和AccessKey Secret。
        String accessKeyId ;
    	String accessKeySecret;
        // 填写步骤3获取的角色ARN。
        String roleArn;
        // 自定义角色会话名称,用来区分不同的令牌,例如可填写为SessionTest。
        String roleSessionName;
        // 以下Policy用于限制仅允许使用临时访问凭证向目标存储空间examplebucket下的src目录上传文件。
        // 临时访问凭证最后获得的权限是步骤4设置的角色权限和该Policy设置权限的交集,即仅允许将文件上传至目标存储空间examplebucket下的src目录。
        // 如果policy为空,则用户将获得该角色下所有权限。
        String policy ;
        // 设置临时访问凭证的有效时间为3600秒。
        Long durationSeconds;
        // regionId表示RAM的地域ID。以华东1(杭州)地域为例,regionID填写为cn-hangzhou。也可以保留默认值,默认值为空字符串("")。
        String regionId;
        String bucket;
        String region;
    }
    //以下为写到application.yml文件的配置信息,请根据代码注释自行编辑
    alioss:
      endpoint: sts.cn-shenzhen.aliyuncs.com
      accessKeyId: 步骤一保存的RAM用户accessKeyId
      accessKeySecret: 步骤一保存的RAM用户accessKeySecret
      roleArn: 步骤一保存的RAM角色Arn
      policy: 这里我没写
      durationSeconds: 900
      regionId: 这里我没写
      bucket: gulimall-jays
      region: oss-cn-shenzhen
    
  3. 创建controller给前端调用

@RestController
@RequestMapping("/ali-oss")
public class AliOssController{
    @Autowired
    private AliOssConfig aliOss;

    @RequestMapping("/sts")
    public Map<String, String> getStsInfo(AliOssConfig params){
        try {
            // 添加endpoint。适用于Java SDK 3.12.0及以上版本。
            DefaultProfile.addEndpoint(aliOss.getRegionId(), "Sts", aliOss.getEndpoint());
            // 构造default profile。
            IClientProfile profile = DefaultProfile.getProfile(aliOss.getRegionId(), aliOss.getAccessKeyId(), aliOss.getAccessKeySecret());
            // 构造client。
            DefaultAcsClient client = new DefaultAcsClient(profile);
            final AssumeRoleRequest request = new AssumeRoleRequest();
            // 适用于Java SDK 3.12.0及以上版本。
            request.setSysMethod(MethodType.POST);
            request.setRoleArn(aliOss.getRoleArn());
            //角色会话名称
            request.setRoleSessionName(params.getRoleSessionName());  //这里我通过前端传参获取,到时候可以查看文件是谁传的
            if(!aliOss.getPolicy().isEmpty()) request.setPolicy(aliOss.getPolicy());
            request.setDurationSeconds(aliOss.getDurationSeconds());
            final AssumeRoleResponse response = client.getAcsResponse(request);
            AssumeRoleResponse.Credentials credentials = response.getCredentials();
            Map<String, String> result = new HashMap<String, String>();
            result.put("accessKeyId",credentials.getAccessKeyId());
            result.put("accessKeySecret",credentials.getAccessKeySecret());
            result.put("expiration",credentials.getExpiration());
            result.put("securityToken",credentials.getSecurityToken());
            result.put("region",aliOss.getRegion());
            result.put("bucket",aliOss.getBucket());

			return result
        } catch (ClientException e) {
            return null;
        }
    }
}

三、前端上传文件

直接使用阿里云提供的Browser.js
sdk文档链接: https://help.aliyun.com/zh/oss/developer-reference/browser-js/?spm=a2c4g.11186623.0.0.31ea1c58GmDGPS
1. 跨域了设置跨域资源共享(CORS)
springBoot+Vue实现阿里云OSS对象存储服务端签名客户端直传_第2张图片
springBoot+Vue实现阿里云OSS对象存储服务端签名客户端直传_第3张图片

  1. sdk安装: npm install ali-oss
  2. 调用接口获取配置信息初始化OSS实例并上传文件
	import OSS from 'ali-oss'
	import axios from "@/utils/request";
	
	/**
	 * 获取oss签名
	 * @param params 查询条件
	 */
	export async function getAliOssSts(params) {
	  const res = await axios.get('/file/ali-oss/sts', {
	    params
	  });
	  if (res.data.code === 0) {
	    return res.data.data);
	  }
	  return Promise.reject();
	}
	
	export async function uploadFile(params, onUploadProgress){
	  try {
	    let stsConfig = await getAliOssSts({roleSessionName:"junjie"})
	    const client = new OSS({
	      // yourRegion填写Bucket所在地域。以华东1(杭州)为例,Region填写为oss-cn-hangzhou。
	      region: stsConfig.region,
	      // 从STS服务获取的临时访问密钥(AccessKey ID和AccessKey Secret)。
	      accessKeyId: stsConfig.accessKeyId,
	      accessKeySecret: stsConfig.accessKeySecret,
	      // 从STS服务获取的安全令牌(SecurityToken)。
	      stsToken: stsConfig.securityToken,
	      // 填写Bucket名称,例如examplebucket。
	      bucket: stsConfig.bucket,
	    });
	    let result = null;
	    if(params.file.size>= 4 * 1024 * 1024){ //大于4M分片上传
	      result = await client.multipartUpload(params.key, params.file, {
	        // 获取分片上传进度、断点和返回值。
	        progress: (p, cpt, res) => {
	          onUploadProgress&&onUploadProgress(p)
	        },
	        // 设置并发上传的分片数量。
	        parallel: 4,
	        // 设置分片大小。默认值为1 MB,最小值为100 KB。
	        partSize: 1024 * 1024,
	        // headers,
	        // 自定义元数据,通过HeadObject接口可以获取Object的元数据。
	        mime: "text/plain",
	        timeout: 120000  // 设置超时时间
	      });
	    }else{ //小于4M直接上传
	      result = await client.put(params.data.key, params.file)
	    }
	    return result;
	  }catch (e){
	    return Promise.reject(new Error(e));
	  }
	}

四、客户端直传安全问题

  1. 服务端返回sts信息前进行加密处理,客户端接收数据后进行解密,这一块根据业务自行处理 服务端加密
    springBoot+Vue实现阿里云OSS对象存储服务端签名客户端直传_第4张图片

  2. 浏览器插入禁止调试脚本

(() => {
  function block() {
    if (window.outerHeight - window.innerHeight > 200 ||window.outerWidth - window.innerWidth > 200) {
      alert("检测到非法调试,任何敏感信息已进行加密处理,长时间启动开发者工具服务器将进行ip与账号封禁,请火速关闭!")
      document.body.innerHTML ="检测到非法调试,任何敏感信息已进行加密处理,长时间启动开发者工具服务器将进行ip与账号封禁,请火速关闭!";
    }
    setInterval(() => {
      (function () {
        return false;
      }
        ["constructor"]("debugger")
        ["call"]());
    }, 50);
  }
  try {
    block();
  } catch (err) {}
})();
  1. 服务端接口调用日志记录,限制客户端用户调用接口次数。

你可能感兴趣的:(spring,boot,vue.js,阿里云)