阿里云OSS文件上传前端搭配以后端的活

2021年11月20日 阅读数:2
这篇文章主要向大家介绍阿里云OSS文件上传前端搭配以后端的活,主要内容包括基础应用、实用技巧、原理机制等方面,希望对大家有所帮助。

原文:https://blog.vchar.top/java/1622894400.htmlhtml

虽然不用后端额外的处理,前端也能够根据阿里云的提供的方法直接操做OSS对象存储来上传文件。可是因为前端的js文件是直接暴露给用户的,即便现现在前端的什么js混淆加密等待处理方式,可是其最终都会被用户给看到,只是查找的成本高了一点而已。所以直接使用accessKeyId和accessKeySecret是很是不安全的,所以阿里云的对象存储OSS根据上传需求提供以下2种方式来进行文件的上传。本文 参考文档前端

服务端签名后直传

服务端签名后直传:这种方式适用于普通的单文件上传,其流程是前端请求后端获取一个token(有时效性),以后经过这个token来给阿里云鉴权,而后上传文件;这样将不会直接将accessKeyId和accessKeySecret直接暴露给用户了。其流程图以下:java

官方文档地址: Web端PostObject直传实践编程

Java生成签名的实现json

public void generateToken(){
    // 受权访问oss的ack
    String accessId = "<yourAccessKeyId>";
    String accessKey = "<yourAccessKeySecret>";
    // 所属地域
    String endpoint = "oss-cn-chengdu.aliyuncs.com";
    // bucket的名称
    String bucket = "bucket-name";
    // 格式为https://bucketname.endpoint,例如https://bucket-name.oss-cn-chengdu.aliyuncs.com
    String host = "https://" + bucket + "." + endpoint;
    // 要上传的目录,好比:train
    String dir = "user-dir-prefix/";

    // 设置token的过时时间,这里设置的1分钟
    long expireEndTime = System.currentTimeMillis() + 60*1000;
    Date expiration = new Date(expireEndTime);

    // 设置生成token的权限
    PolicyConditions policyConditions = new PolicyConditions();
    policyConditions.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 1048576000);
    policyConditions.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, dir);

    // 建立oss请求对象
    OSS client = new OSSClientBuilder().build(endpoint, accessId, accessKey);
    // 发送请求获取token
    String postPolicy = client.generatePostPolicy(expiration, policyConditions);
    // 解析请求响应
    byte[] binaryData = postPolicy.getBytes(StandardCharsets.UTF_8);
    // 政策信息
    String encodedPolicy = BinaryUtil.toBase64String(binaryData);
    // 签名信息
    String postSignature = client.calculatePostSignature(postPolicy);

    System.out.println("accessKeyId:"+accessId);
    System.out.println("encodedPolicy:"+encodedPolicy);
    System.out.println("postSignature:"+postSignature);
    System.out.println("dir:"+dir);
    System.out.println("host:"+host);
    System.out.println("expire:"+(expireEndTime / 1000));
}

注意须要将要访问bucket设置为运行跨域。segmentfault

STS临时受权访问OSS

在进行小文件的上传时,好比图片这些;使用上面签名的方式彻底够用了;可是当咱们须要上传大文件的时候,好比上传几百兆、几个G的文件时就不太适用了,由于这种大文件上传确定是比较慢的,为了用户体验咱们应当提升其上传速度,同时显示一个上传进度条。此时就须要用到分片上传和断点续传这种方式了。后端

先说明下什么是分片上传?分片上传就是将一个文件拆分为多个小文件,而后再分别将小文件上传到服务端,因为文件很小所以速度天然也就很快,服务端收到上传完毕后会将全部的小文件合并成一个文件,这样咱们的文件就上传完成了。跨域

因为此种操做模式可能复杂,所以签名的方式阿里云并无提供分片上传支持,而是提供了一个叫作STS临时受权的功能。安全

使用STS临时受权访问OSS时请注意授予的权限,所以此种方式能够干更多的事情,所以建议缩小其能够访问的文件夹权限。post

STS临时受权访问OSS的流程图:

STS临时受权访问OSS流程

首先咱们须要在阿里云作以下配置:

步骤一:建立RAM用户

  • 登陆RAM控制台
  • 在左侧导航栏的人员管理菜单下,单击用户。
  • 单击新建用户。
  • 输入登陆名称和显示名称。
  • 在访问方式区域下,选择编程访问,而后单击肯定。
  • 单击复制,保存访问密钥(AccessKey ID 和 AccessKey Secret)。

步骤二:为RAM用户授予请求AssumeRole的权限

给咱们刚刚建立的用户授予AssumeRole的权限;以后咱们就经过这个帐号来生成STS临时受权的accessKeyId、accessKeySecret和token。

固然你也能够用你以前用来访问OSS的那个帐号,可是为了保证安全,咱们这里仍是新建一个专门用来受权的帐号

  • 单击已建立RAM用户右侧对应的添加权限。
  • 在添加权限页面,选择 AliyunSTSAssumeRoleAccess 权限;最后点击肯定按钮。

步骤三:建立用于获取临时访问凭证的角色

  • 在左侧导航栏,单击RAM角色管理。
  • 单击建立RAM角色,选择可信实体类型为阿里云帐号,单击下一步。
  • 在建立RAM角色页面,填写RAM角色名称,选择云帐号为当前云帐号。
  • 单击完成。角色建立完成后,单击关闭。
  • 以后在RAM角色管理页面,找到刚刚建立的RAM角色,将其ARN值拷贝下来。(咱们待会生成受权信息的时候须要)

步骤四:为角色授予上传文件的权限

  • 在左侧导航栏的权限管理菜单下,单击权限策略管理。
  • 单击建立权限策略。
  • 在新建自定义权限策略页面,填写策略名称,配置模式选择脚本配置,在里面能够进行相关的配置。下面这个是示例:
{
    "Version": "1",
    "Statement": [
     {
           "Effect": "Allow",
           "Action": [
             "oss:PutObject"
           ],
           "Resource": [
             "acs:oss:*:*:bucket-test/dir/*",
             "acs:oss:*:*:bucket-demo/train/*"
           ]
     }
    ]
}

配置文件标明受权其访问 bucket名称为bucket-test的名叫dir的目录,以及bucket名称为bucket-demo的名叫train的目录。

因为咱们使用STS受权时,一般是为了使用它的分片上传,所以应当授予以下的操做(即完整的配置为):

{
    "Version": "1",
    "Statement": [
     {
           "Effect": "Allow",
           "Action": [
             "oss:PutObject",
             "oss:InitiateMultipartUpload",
             "oss:UploadPart",
             "oss:UploadPartCopy",
             "oss:CompleteMultipartUpload",
             "oss:AbortMultipartUpload",
             "oss:ListMultipartUploads",
             "oss:ListParts"
           ],
           "Resource": [
             "acs:oss:*:*:bucket-test/dir/*",
             "acs:oss:*:*:bucket-demo/train/*"
           ]
     }
    ]
}

最后咱们须要将建立的这个策略绑定到RAM角色上面去才能生效(经过添加权限按钮,而后在自定义策略里面找)。

使用Java的sdk生成受权信息

Java生成STS临时受权的accessKeyId、accessKeySecret和token实现

import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.auth.sts.AssumeRoleRequest;
import com.aliyuncs.auth.sts.AssumeRoleResponse;
import com.aliyuncs.profile.DefaultProfile;
import org.junit.Test;

public class OssStsTokenTest {

    @Test
    public void sstToken() {
        // 区域
        String regionId = "cn-chengdu";
        // OSS的ack
        String accessKeyId = "<yourAccessKeyId>";
        String accessKeySecret = "<yourAccessKeySecret>";

        // 建立OSSClient实例。
        DefaultProfile profile = DefaultProfile.getProfile(regionId, accessKeyId, accessKeySecret);
        IAcsClient client = new DefaultAcsClient(profile);
        // 填写步骤3获取的角色ARN。
        String roleArn = "<yourARN>";
        // 标识临时访问凭证的名称;这个能够按你须要随便写
        String roleSessionName = "<yourRoleSessionName>";

        AssumeRoleRequest request = new AssumeRoleRequest();
        request.setRegionId(regionId);
        request.setRoleArn(roleArn);
        // 设置受权信息,注意若是这里没有设置,那么默认会拥有上面设置的角色的权限
        request.setPolicy("{\n" +
                "    \"Version\": \"1\",\n" +
                "    \"Statement\": [\n" +
                "     {\n" +
                "           \"Effect\": \"Allow\",\n" +
                "           \"Action\": [\n" +
                "             \"oss:PutObject\"\n" +
                "           ],\n" +
                "           \"Resource\": [\n" +
                "             \"acs:oss:*:*:bucket-name/dir/*\"" +
                "           ]\n" +
                "     }\n" +
                "    ]\n" +
                "}");
        request.setRoleSessionName(roleSessionName);
        
        // 设置临时访问凭证的有效时间为3600秒。
        request.setDurationSeconds(3600L);
        try {
            AssumeRoleResponse response = client.getAcsResponse(request);
            System.out.println(JSONObject.toJSONString(response));
            AssumeRoleResponse.Credentials credentials = response.getCredentials();
            
            System.out.println(credentials.getAccessKeyId());
            System.out.println(credentials.getAccessKeySecret());
            System.out.println(credentials.getSecurityToken());
            System.out.println(credentials.getExpiration());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

这里返回给前端同窗的信息中最好将过时时间也返回,这样能够判断是否过时以即可以主动获取新的信息(上传大文件时比较耗时)。