相关文章推荐
想发财的野马  ·  C# ...·  6 月前    · 
想发财的野马  ·  Error: Unable to ...·  7 月前    · 
想发财的野马  ·  golang ...·  7 月前    · 
想发财的野马  ·  python zmq socket timeout·  10 月前    · 
文雅的沙滩裤  ·  WKWebView拦截请求资源 ·  1小时前    · 
独立的眼镜  ·  如何连接Babelfish for RDS ...·  2 小时前    · 
发财的蛋挞  ·  Microsoft Azure Data ...·  2 小时前    · 
冷冷的投影仪  ·  Secure an ASP.NET ...·  3 小时前    · 
不羁的生姜  ·  PSPSDK 开发的时候出现 ...·  3 小时前    · 
  • 应用案例
  • 新手教学
  • 文档中心
  • 关于我们
  • # 对象存储

    针对各个公有云和私有云提供功能不同,为了使上层开发与具体应用解耦,所以提供 SDK 适配各个云厂商,供上层服务调用。可以通过简单的切换配置文件,达到切换不同厂商的功能。

    # 功能介绍

    ObjectStorage 是为了适配多云的对象存储而开发的 SDK ,用于支持产品在多个云的环境部署运行。产品可以通过简单的修改配置,不用修改代码就能完成在多云之间的平滑部署迁移。

    • 适配了阿里云的 OSS ,华为云的 OBS ,腾讯云的COS,以及私有化环境下的 minio ceph 以及青云。
    • 支持对象存储的各种操作:上传文件,下载文件,签名直传,缩略图,视频截帧等。
    • 支持通过临时授权STS的方式获取临时密钥,进行对象存储的访问。

    基于 ObjectStorage 提供的便捷,为了在使用上可以更加方便,我们提供了 object-storage-spring-boot-starter ,其内部是基于 ObjectStorage 的实现,为上层提供了自动配置的功能,也就是 starter 包。

    # 使用流程

    # 1.配置settings.xml私仓地址

    <!-- scg maven仓库 -->
    <repository>
        <id>scg-private</id>
        <name>maven-scg-private</name>
        <url>http://packages.glodon.com/artifactory/maven-scg-private/</url>
    </repository>
    
    1
    2
    3
    4
    5
    6

    # 2.项目中添加 pom 依赖

    <dependency>
        <groupId>com.glodon.cloud</groupId>
        <artifactId>object-storage-spring-boot-starter</artifactId>
         <version>1.0.4</version>
    </dependency>
    
    1
    2
    3
    4
    5

    如果结合 spring-cloud-glodon 使用,则通过引入 spring-cloud-glodon-dependencies 后管理依赖版本即可

    <dependency>
        <groupId>com.glodon.cloud</groupId>
        <artifactId>object-storage-spring-boot-starter</artifactId>
    </dependency>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>com.glodon.cloud</groupId>
                <artifactId>spring-cloud-glodon-dependencies</artifactId>
                <version>2.3.2.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16

    # 3.配置yaml

    object-storage:
    	protocol: S3_HW #可选项 OSS、S3_HW、S3_COS、S3_AWS、S3_AWS_V4、S3_MINIO、S3_CEPH、S3_QY、S3
        endPoint: your.end-point
        accessKeyId: your.access.key.id
        accessKeySecret: your.access.key.secret
        # 新增可选配置项
        region: your-region
        pathStyleAccess: true/false # 是否强制开启路径形式的资源访问
        externalEndpoint: your-external-endpoint # 是否使用对外的endpoint,默认false。在对象存储的某些操作中,例如获得签名URL时,需要给用户对外的endpoint
        maxConnections: # 连接数
        connectionTimeout: # 连接超时时间
        socketTimeout: # socket超时时间
        # 废弃配置项: 老版本的图片处理和视频处理等功能需要配置云厂商,当前新版本无需配置即可使用
        provider: ali/huawei
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14

    配置项说明:

    /**
         * 是否强制开启路径形式的资源访问
         * (指定为Boolean.TRUE,那么使用endpoint/bucket的方式来访问)
         * (指定为Boolean.FALSE,那么使用bucket.endpoint的方式来访问)
         * (不指定则为null,使用OSS或者S3的默认方式:
         *      OSS默认采用bucket.endpoint;
         *      S3默认对于ip格式的endpoint和非合法DNS格式的bucket采用endpoint/bucket,
         *          而其他情况使用bucket.endpoint;
         *      S3_HW:与S3默认情况相同;
         *      S3_QY:与S3默认情况相同;
         *      S3_CEPH:默认使用endpoint/bucket方式访问
         *      S3_MINIO: 默认使用endpoint/bucket方式访问;
         *      )
         *  默认值大多数情况下足够使用,绝大多数情况不需要指定这个参数
    private Boolean pathStyleAccess;
    	* 该配置项当前主要针对,签名直传功能的接口,可以通过externalEndpoint控制获取到的host是内网还是外网
    private String externalEndpoint;
    
    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

    # 4.注入对象

    配置完成后,就可以在代码中注入 ObjectClient 来使用。

    @Autowired
    ObjectClient objectClient;
    
    1
    2

    # 5.常用操作

    # 5.1 文件上传下载

    // 上传文件
    ObjectBasicInfo objectBasicInfo = new ObjectBasicInfo(bucketName, fileName);
    objectClient.put(objectBasicInfo, file);
    // 下载文件
    ObjectBasicInfo objectBasicInfo = new ObjectBasicInfo(bucketName, fileName);
    objectClient.get(objectBasicInfo, file);
    
    1
    2
    3
    4
    5
    6
    7
    8

    # 5.2 获取签名URL

    ObjectBasicInfo objectBasicInfo = new ObjectBasicInfo(bucketName, fileName);
    String strUrl = objectClient.getSignedURL(objectBasicInfo, 600, "", SignedUrlBehavior.DOWNLOAD, null).toString();// 过期时间设置成600s
    
    1
    2

    # 5.3 图片操作

    // 1.先定义 DataProcessor
    DataProcessor processor = new DataProcessor(DataProcessor.Type.IMAGE, Collections.singletonList("resize,w_100,h_100"));
    // 2.调用下面两个方法之一
    ObjectClient.getSignedURL(ObjectBasicInfo objectBasicInfo, int expiredTime, String fileName,SignedUrlBehavior behavior, DataProcessor processor);
    RawClient.getSignedURL(SignedURLRequest signedURLRequest);
    
    1
    2
    3
    4
    5

    针对华为云和阿里OSS,图片处理是全功能支持的。

    针对ceph、minIO、QingYunS3,图片处理功能是在object-storage中自己实现的。实现方式是基于github上的开源项目thumbnailator: 前往GitHub查看

    仅支持了resize 操作,format操作。resize 功能与阿里云保持一致,但是调用resize,允许放大和缩小(没有实现limit_0和limit_1功能)。

    在一个action中,参数优先级[w,h]>l>s>p,高优先级的参数将覆盖低优先级的参数操作,与出现的顺序无关,同一个参数出现多次,后面的会覆盖前面的,参数m没有优先级。

    原理:先将图片下载下来,然后使用工具处理之后,将处理后的图片上传至同一个bucket下的ImageProcessTempFolder文件夹内。文件名字为:etag+actions+format

    # 5.4 视频截帧

    // 1.定义 processor
    DataProcessor processor = new DataProcessor(DataProcessor.Type.VIDEO,
                    Collections.singletonList("snapshot,t_5000,f_jpg,w_800,h_600,m_fast"));
    // 2.调用下面两个方法之一获取截图
    ObjectClient.getSignedURL(ObjectBasicInfo objectBasicInfo, int expiredTime, String fileName,SignedUrlBehavior behavior, DataProcessor processor));
    RawClient.getSignedURL(SignedURLRequest signedURLRequest);
    
    1
    2
    3
    4
    5
    6
    7
    参数 描述 取值范围
    t 截图时间 单位ms,[0,视频时长]
    w 截图宽度,如果指定为0则按照比例自动计算 像素值:[0,视频宽度]
    h 截图高度,如果指定为0则按照比例自动计算,如果w和h都为0则输出为原视频宽高 像素值:[0,视频高度]
    m 截图模式,不指定则为默认模式,根据时间精确截图,如果指定为fast则截取该时间点之前的最近的一个关键帧 枚举值:fast
    f 输出图片格式 枚举值:jpg、png

    # 5.5 签名直传

    PostPolicyRequest postPolicyRequest = new PostPolicyRequest(600, 1000L, "your-bucket");
    PostPolicyInfo postPolicyInfo = objectClient.generatePostPolicy(postPolicyRequest);
    
    1
    2

    拿到 postPolicyInfo 后,浏览器发起的请求应该如下

     curl -X POST ${info.host} \
      -H 'content-type: multipart/form-data' \
      -F 'key=ABCD.file' \
      -F policy=${info.encodedPolicy} \
      -F ${info.accessIdName}=${info.accessId} \
      -F callback=${info.callback} \
      -F signature=${info.postSignature} \
      -F success_action_status=200 \
      -F 'file=@/your/path/ABCD.file' 
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    # 5.5.1 示例

    服务端需要提供获取签名信息的接口(本示例以java为例)

    @RestController
    @CrossOrigin(allowCredentials = "true")
    public class ObjectStorageController {
        @Autowired
        private ObjectClient objectClient;
        @GetMapping("signature")
        public String getSignature(){
            PostPolicyRequest postPolicyRequest = new PostPolicyRequest(600, 10 * 1024 * 1024L, bucketName);
            PostPolicyInfo postPolicyInfo = objectClient.generatePostPolicy(postPolicyRequest);
            return JSONObject.toJSONString(postPolicyInfo);
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14

    前端html

    <!DOCTYPE html>
    <html lang="en">
        <meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
        <title>OBS web直传</title>
    </head>
    <h2 align="center">web直传</h2>
        <p align="center">
            <input type="file" id="post_file" name="post_file">
        <p align="center">
            <button type="submit" value="上传" class="btn btn-success" onclick="postFile()">上传</button>
    </div>
    </body>
    <script type="text/javascript">
        function postFile() {
            // 获取签名的服务端地址
            const signUrl = "http://localhost:9000/signature";
            // 1.获取文件
            const resultFile = document.getElementById("post_file").files[0];
            // 2.获取签名 result, 结构如下
              "accessId": "XXXXXXX",
              "accessIdName": "OSSAccessKeyId",
              "contentDisposition": "inline/attachment",
              "contentType": "application/octet-stream",
              "encodedPolicy": "XXXXXX",
              "expireTimeSeconds": 1603784561,
              "host": "XXXXXX",
              "postPolicy": "{expiration:xxxxxx,conditions:[[content-length-range,0,10485760],{bucket:xxxxxx},{success_action_status:200},{Content-Disposition:xxxxxx},{Content-Type:xxxxxx},[starts-with,$key,xxxxxx]]}",
              "postSignature": "xxxxxxx"
            const result = getSignature(signUrl);
            // 3.解析从服务端获取到的签名和策略相关的信息
            const policy = resolvePostPolicy(result.postPolicy);
            // 4.上传 (注意设置 isS3 参数)
            let uploadResult = postObjectByAjax(resultFile, result.accessId, result.encodedPolicy,
                result.postSignature, result.host, policy.contentType, policy.contentDisposition, policy.keyPrefix, false);
            if (uploadResult === true) {
                alert("上传成功")
            } else {
                alert("上传失败")
    </script>
    <script src="https://yzl-oss-test.oss-cn-beijing.aliyuncs.com/objectstorage-web/objectstorage.js"></script>
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
    <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
    <script src="https://cdn.bootcss.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
    <link rel="stylesheet" href="http://cdn.bootcss.com/bootstrap/3.3.5/css/bootstrap.min.css">
    </html>
    
    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

    注意

    上述html中https://yzl-oss-test.oss-cn-beijing.aliyuncs.com/objectstorage-web/objectstorage.js是云中立提供的objectstorage.js下载地址,可以直接引用;若需要修改,也可以从下方示例下载链接中下载后修改使用。

    objectstorage.js文件

    /**
     * @Author: baijd-a
     * @Date: 2020-10-26 15:58:29
     * @LastEditTime: 2020-10-26 15:58:29
     * @LastEditors: baijd-a
     * @Description: 采用云中立平台的对象存储适配,下面代码演示了前端如何采用签名直传的方式上传文件到 OSS、S3
     * 针对请求方式可采用 ajax axios
     * 根据url从服务端获取签名直传的签名相关信息
     * @param url
     * @returns 签名相关信息
    function getSignature(url) {
        let result = null;
        $.ajax({
            url: url,
            type: "get",
            async: false,
            success: function (data) {
                result = JSON.parse(data);
        });
        return result;
     * 通过 Ajax 上传文件到云服务
     * 注意:
     *      请求时 FormData 参数中的 Content-Type, Content-Disposition, keyPrefix 需要和后端返回的策略中保持一致
     * @param file 文件
     * @param accessId AK
     * @param policy 上传策略 base64值
     * @param signature 签名
     * @param host 上传的host
     * @param contentType 上传的Content-Type ===> 从服务端获取到的 Policy 中的值
     * @param contentDisposition 展示形式:内联(inline),附件下载(attachment; filename="xxx") ===> 从服务端获取到的 Policy 中的值
     * @param objectKeyPrefix 上传的key前缀
     * @param isS3 是否是S3服务[华为云、腾讯云、MINIO、CEPH、AWS]
    function postObjectByAjax(file, accessId, policy, signature, host, contentType, contentDisposition, objectKeyPrefix, isS3) {
        let form = new FormData();
        if (isS3) {
            form.append('AWSAccessKeyId', accessId); // S3 的 accessID; 若是上传到 S3 采用这个参数
        } else {
            form.append('OSSAccessKeyId', accessId);  // OSS 的 accessID; 若是上传到 OSS 采用这个参数
        form.append('policy', policy);
        form.append('signature', signature);
        if (contentType !== null && contentType !== '') {
            form.append("Content-Type", contentType);
        if (contentDisposition !== null && contentDisposition !== '') {
            form.append("Content-Disposition", contentDisposition)
        if (objectKeyPrefix == null) {
            objectKeyPrefix = '';
        } else if (objectKeyPrefix !== '' && !objectKeyPrefix.endsWith("/")) {
            objectKeyPrefix += "/";
        form.append('key', objectKeyPrefix + file.name);  // key: 文件上传的完整路径 若有目录含有目录
        form.append('success_action_status', 200); // 文件上传成功后返回的状态
        form.append('file', file);
        return _ajaxPostObject(host, form);
    function _ajaxPostObject(url, formData) {
        var result = false;
        $.ajax({
            type: "POST",
            url: url,
            data: formData,
            processData: false,
            cache: false, // 设置为false将不会从浏览器缓存中加载请求信息
            async: false, // 发送同步请求
            contentType: false, // 避免服务器不能正常解析文件
            // dataType: 'JSONP', // jsonp只能提供get请求; 不涉及跨域, 写json即可
            success: function (data) {
                result = true;
        });
        return result;
     * 通过 Axios 上传文件到云服务
     * 注意:
     *      请求时 FormData 参数中的 Content-Type, Content-Disposition, keyPrefix需要和后端返回的策略中保持一致
     * @param file 文件
     * @param accessId AK
     * @param policy 上传策略 base64值
     * @param signature 签名
     * @param host 上传的host
     * @param contentType 上传的Content-Type  ===> 从服务端获取到的 Policy 中的值
     * @param contentDisposition 展示形式:内联(inline),附件下载(attachment; filename="xxx") ===> 从服务端获取到的 Policy 中的值
     * @param objectKeyPrefix 上传的key前缀
     * @param isS3 是否是S3服务[华为云、腾讯云、MINIO、CEPH、AWS]
    function postObjectByAxios(file, accessId, policy, signature, host, contentType, contentDisposition, objectKeyPrefix, isS3) {
        let form = new FormData();
        if (isS3) {
            form.append('AWSAccessKeyId', accessId); // S3 的 accessID; 若是上传到 S3 采用这个参数
        } else {
            form.append('OSSAccessKeyId', accessId);  // OSS 的 accessID; 若是上传到OSS 采用这个参数
        form.append('policy', policy);
        form.append('signature', signature);
        form.append('signature', signature);
        if (contentType !== null && contentType !== '') {
            form.append("Content-Type", contentType);
        if (contentDisposition !== null && contentDisposition !== '') {
            form.append("Content-Disposition", contentDisposition)
        if (objectKeyPrefix == null) {
            objectKeyPrefix = '';
        } else if (objectKeyPrefix !== '' && !objectKeyPrefix.endsWith("/")) {
            objectKeyPrefix += "/";
        form.append('key', objectKeyPrefix + file.name);  // key: 文件上传的完整路径 若有目录含有目录
        form.append('success_action_status', 200); // 文件上传成功后返回的状态,默认204
        form.append('file', file);  // 文件流
        let config = {
            header: {
                'Content-Type': 'multipart/form-data;',
        axios.post(host, form, config)
            .then(res => {
                console.log('上传成功');
            .catch(error => {
                console.log('上传失败');
                console.log(error)
            });
     * 判断对象是否为数组
     * @param o 要判断的对象
     * @returns {boolean} 判断结果
    function isArray(o) {
        return Object.prototype.toString.call(o) === '[object Array]';
     * 将后端返回的结构中的策略 Policy json 进行解析
     * @param postPolicyJson Policy json
     * @returns {{contentDisposition: string, contentType: string, keyPrefix: string}}
    function resolvePostPolicy(postPolicyJson) {
        // 解析从服务端获取到的签名和策略相关的信息
        let contentDisposition = '';
        let contentType = '';
        let keyPrefix = '';
        const postPolicy = JSON.parse(postPolicyJson);
        const conditions = postPolicy.conditions;
        for (let i = 0; i < conditions.length; i++) {
            const condition = conditions[i];
            if (isArray(condition) && condition[0] === 'starts-with') {
                keyPrefix = condition[2];
            } else {
                if (condition['Content-Type'] !== undefined) {
                    contentType = condition['Content-Type'];
                if (condition['Content-Disposition'] !== undefined) {
                    contentDisposition = condition['Content-Disposition'];
        return {
            contentType: contentType,
            contentDisposition: contentDisposition,
            keyPrefix: keyPrefix
    
    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
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185

    服务端http://localhost:9000/signature返回结果:

    {
        "accessId": "xxxxx",
        "accessIdName": "OSSAccessKeyId",
        "encodedPolicy": "xxxxxxx",
        "expireTimeSeconds": 1603790181,
        "host": "https://xxxxxx.com",
        "postPolicy": "{expiration:xxxxxx,conditions:[[content-length-range,0,10485760],{bucket:xxxxxx},{success_action_status:200},{Content-Disposition:xxxxxx},{Content-Type:xxxxxx},[starts-with,$key,xxxxxx]]}",
        "postSignature": "xxxxxx"
    
    1
    2
    3
    4
    5
    6
    7
    8
    9

    阿里云上传结果:

    General
        Request URL: https://xxxxxx.com/
        Request Method: POST
        Status Code: 200 OK
        Remote Address: xxx.xxx.xxx.xxx
        Referrer Policy: strict-origin-when-cross-origin
    Form Data
        OSSAccessKeyId: xxxxxx
        policy: xxxxxx
        key: test1/xxxxxx.txt
        success_action_status: 200
        file: (binary)
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    # 5.5.2 示例下载链接

    示例下载链接

    # 5.6 sts临时授权访问对象存储

    STS(Security Token Service),可以进行临时授权访问。通过STS,您可以为第三方应用或子用户(即用户身份由您自己管理的用户)颁发一个自定义时效和权限的访问凭证。

    阿里云 STS

    华为云 STS

    腾讯云 STS

    亚马逊 STS

    注意:由于临时授权访问密钥需要使用子用户的AK,SK进行API调用,所以如果没有子用户,请自建子用户,且分配S3操作权限。参考 官网

    MINIO STS

    环境搭建步骤:根据minio光网介绍,我们可以通过AssumeRole方式获取临时访问密钥,其余实现方式参考 Minio官网

    注意:由于为临时授权访问密钥,所以此处需要使用子用户的AK,SK进行API使用,如果没有,请自建子用户。

    # 5.6.1 阿里云示例

    yaml配置

    object-storage:
      end-point: https://your-region.aliyuncs.com
    sts:
      protocol: OSS
      # sts-endpoint: # 阿里云有默认的stsEndpoint,也可以自己指定
      accessKeyId: xxxxxx
      accessKeySecret: xxxxxx
      roleArn: acs:ram::xxxxxx:role/xxxxxx # roleArn配置,STS获取临时授权需要用到
    
    1
    2
    3
    4
    5
    6
    7
    8

    上述配置肿的sts,已经配置了一个sts的客户端stsClient,我们可以直接注入即可

    @Autowired
    private StsClient stsClient;
    
    1
    2

    然后我们需要根据stsClient获取临时密钥,用临时密钥构造一个对象存储的客户端注入spring容器使用

    此处以阿里云为例,指定特定bucket下的resource权限*

    @Bean
    public ObjectClient objectClient() {
        final String[] actions = {"oss:*"};
        final String[] resources = {"acs:oss:*:*:" + your-bucketName, "acs:oss:*:*:" + your-bucketName + "/*"};
    	// 根据上述指定的 actions和 resources,构造请求策略
        StsRequestPolicyStatement statement = new StsRequestPolicyStatement.Builder()
            .action(actions)
            .resource(resources)
            .build();
        StsRequestPolicy stsRequestPolicy = new StsRequestPolicy.Builder()
            .statement(new StsRequestPolicyStatement[]{statement})
            .build();
        // 根据构造的请求策略和临时密钥有效时常,获取临时密钥
        StsResponse stsResponse = stsClient.getStsResponse(stsRequestPolicy, 15 * 60);
        System.out.println(stsResponse.toString());
    	// 根据获取的临时密钥构造ObjectClient的配置
        RawClientConfig.Builder configBuilder = RawClientConfig.builder()
            .endpoint(endpoint)
            .accessKeyId(stsResponse.getAccessKeyId())
            .secretAccessKey(stsResponse.getAccessKeySecret())
            .securityToken(stsResponse.getSecurityToken());
        if (StringUtils.isNotBlank(region)) {
            configBuilder.region(region);
    	// 根据配置构造ObjectClient,注入spring容器
        return new ObjectClient(configBuilder.build(), ClientType.valueOf(protocol.toUpperCase()),
                                null, null);
    
    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

    这样,就可以在您的应用中使用上述的ObjectClient

    @Autowired
    private ObjectClient objectClient;
    
    1
    2

    注意:

    由于临时密钥有有效时常限制,所以请注意临时密钥的过期。我们预留了接口供您在过期前更新临时密钥

    // 获取新的临时密钥
    StsResponse stsResponse = stsClient.getStsResponse(......);
    // 更新临时密钥
    objectClient.updateTempKeyAndSecret(stsResponse.getAccessKey(), stsResponse.getAccessSecret(), stsResponse.getSecurityToken());
    
    1
    2
    3
    4
    # 5.6.2 S3相关示例

    注意,目前S3相关的云对象存储中,支持STS的只有:华为云、腾讯云、亚马逊、MINIO云;所以如果要使用对象存储的STS功能,请在指定客户端类别时指定以上类型。

    华为云:

    yaml配置

    object-storage:
      end-point: http://obs.your-region.myhuaweicloud.com
    sts:
      protocol: S3_HW
      # sts-endpoint: # 华为云云有默认的stsEndpoint,也可以自己指定
      accessKeyId: xxxxxx
      accessKeySecret: xxxxxx
      ima-domain-name: your-domain-name
      ima-user-name: your-ima-user-name
      ima-password: your-ima-user-password
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10

    API调用:参见阿里云

    腾讯云:

    yaml配置

    object-storage:
      end-point: cos.your-region.myqcloud.com
    sts:  
      access-key-id: xxxxxx
      access-key-secret: xxxxxx
      protocol: S3_COS
      # 腾讯云STS获取临时授权时需要配置region和一个bucket
      bucket: your-bucket
      region: your-region
    
    1
    2
    3
    4
    5
    6
    7
    8
    9

    API调用:参见阿里云

    AWS、AWS_V4:

    yaml配置

    object-storage:
      end-point: https://s3.your-region.amazonaws.com
      region: your-region
    sts:  
      access-key-id: xxxxxx
      access-key-secret: xxxxxx
      protocol: S3_AWS/S3_AWS_V4
      region: your-region
      role-arn: arn:aws:iam::your:role/name
      external-id: Required # 可选
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10

    API调用:参见阿里云

    MINIO:

    yaml配置

    object-storage:
      end-point: http://your-minio-host:port
    sts:
      stsEndpoint: your-sts-endpoint
      access-key-id: xxxxxx # 字用户id
      access-key-secret: xxxxxx # 字用户secret
      protocol: S3_MINIO
    
    1
    2
    3
    4
    5
    6
    7

    API调用:参见阿里云

    # 5.6.3 注意事项

    1.上述示例中指定的各个action,resource请以各个云平台官网为准,如果您需要指定您的action、resource,请参考各个平台对应的官方文档介绍。

    2.各个平台对应的指定生成临时秘钥的最短和最长有效时长有差异,请以各个平台官方文档为准,上述示例仅为参考。

    3.由于各个平台需要的配置各有差异,所以当您切换平台时,请注意在yaml配置文件中修改相应的配置进行使用。

    阿里云:需要配置角色的ARN -> roleArn

    华为云:需要配置IAM用户所属账号信息、IAM用户名、IAM用户的登录密码 -> imaDomainName,imaUserName,imaPassword

    腾讯云:腾讯云对象存储 获取临时密钥时需要且只能指定一个bucket,且需要指定region -> bucket,region

    亚马逊:AWS对象存储需要指定配置角色的ARN和ExternalId(创建用户/角色时指定的)-> roleArn,externalId

    MINIO云:需要配置stsEndpoint

    4.由于各平台返回的临时秘钥中有效时间格式不同,所以本SDK统一使用阿里云的时间格式:2020-12-02T03:15:56Z,返回GMT时间。

    # 5.6.4 常见错误

    1.腾讯云 InvalidParameter.ResouceError

    使用腾讯云出现如下错误
    {"Response":{"Error":{"Code":"InvalidParameter.ResouceError","Message":"[QC_STS] resource error"},"RequestId":"xxxxxxxx"}}
    
    1
    2
    3

    解决方案:

    由于腾讯云内部实现中使用了org.json包,所以确保您的应用中存在该包,且没有与其余包(例如:android-json)混淆,出现错误调用。

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
        <exclusions>
            <exclusion>
                <artifactId>android-json</artifactId>
                <groupId>com.vaadin.external.google</groupId>
            </exclusion>
        </exclusions>
    </dependency>
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    推荐文章