You need to enable JavaScript to run this app.
导航

使用临时鉴权 URL 实现数据安全下载

最近更新时间2023.09.18 14:05:58

首次发布时间2023.05.30 16:34:07

您可以通过临时 URL 访问 TOS,实现数据的安全上传及下载。本文介绍使用临时鉴权 URL 访问 TOS 的方案说明及操作步骤。

场景说明

在视频监控、APP、Web 等应用情况下,通常有很多图片、文件、视频等信息需要上传到服务端,或者从服务端下载到本地进行使用。在这种业务应用场景下, 你可以充分使用对象存储的 HTTP 访问属性,实现低成本、高质量的数据传输逻辑,同时因为 TOS 服务的 Serverless,可以很好的应对业务的增长或缩小,很好的实现了业务的弹性适配。

方案说明

方案架构图

alt

角色说明

  • 终端: 受后端 Server 控制,实现最终环境人机或机机交互,按照不同流程进行数据的上传或者下载使用。

  • APP Sever:整个业务系统的大脑,负责对终端的管理和权限控制,在此业务中主要负责临时 URL 的生成。

  • TOS 服务:提供 HTTP 接口的 KV 类型的存储系统。

  • IAM 服务:提供公有云服务的账户和用户的权限控制。

方案概述

  1. APP Server 需要先创建一个 IAM 子用户,同时授权子用户具有访问对象存储桶以及桶中对象的权限并获取子用户的 AK 及 SK 信息。

  2. 当终端向 APP Server 申请发送请求的临时 URL 时,APP Server 根据上传下载行为生成具备有效期的临时鉴权 URL;同时 APP Server 将上传或下载的对象进行数据库记录,方便业务使用。

  3. 终端获取到临时 URL 后,根据该 URL 和 TOS 服务交互,进行上传或者下载行为。

  4. TOS 服务端收到请求后,向 IAM 交互获取对应的密钥,然后使用此密钥进行签名计算,并和客户端的请求进行对比,确定是否合法;合法后则进行业务处理。

  5. 终端收到请求的处理结果,流程结束。

优劣势

使用临时 URL 上传下载方案的优劣势如下所示。

优劣势详情

优势

  1. 临时 URL 签名认证到对象级别,安全性高。

  2. 终端开发只需要支持 HTTP 请求发送即可,开发简单快捷。

  3. 终端不用支持各个不同云厂商的对象存储接口,可以实现多云的业务切换。

劣势

  1. 每个请求都需要服务端进行签发,当终端数量增长后,会增大服务端的压力。

  2. 因并发上传操作困难,不利于大文件的上传。

操作步骤

前提条件

实施步骤

步骤一:APP Server 开发配置

  1. 根据业务需要,获取不同语言的 SDK。

    根据您的 APP Server 架构设计中开发语言的选择,选择对应语言的 TOS SDK 集成开发,加速开发进程。
      TOS 支持的 SDK 语言,请参见 SDK 概述

  2. 业务代码集成开发。

    本文以 Go 语言为例,介绍如何生成临时 URL 下载对象。

    说明

    其他语言生成临时 URL 的示例代码,请参见 SDK 概述

package main

import (
   "context""fmt""github.com/volcengine/ve-tos-golang-sdk/v2/tos"
)
func checkErr(err error) {
   if err != nil {
      if ServerErr, ok := err.(*tos.TosServerError); ok {
         fmt.Println("Error:", ServerErr.Error())
         fmt.Println("Request ID:", ServerErr.RequestID)
         fmt.Println("Response Status Code:", ServerErr.StatusCode)
         fmt.Println("Response Header:", ServerErr.Header)
         fmt.Println("Response Err Code:", ServerErr.Code)
         fmt.Println("Response Err Msg:", ServerErr.Message)
      } else if clientErr, ok := err.(*tos.TosClientError); ok {
         fmt.Println("Error:", clientErr.Error())
         fmt.Println("Client Cause Err:", clientErr.Cause.Error())
      } else {
         fmt.Println("Error:", err)
      }
      panic(err)
   }
}

func main() {
   var (
      accessKey = "*** Provide your access key ***"
      secretKey = "*** Provide your secret key ***"// Bucket 对应的 Endpoint,以华北2(北京)为例:https://tos-cn-beijing.volces.com
      endpoint = "https://tos-cn-beijing.volces.com"
      region   = "cn-beijing"// 填写 RegionID
      bucketName = "*** Provide your bucket name ***"
      objectKey = "example_dir/example.txt" 
      ctx       = context.Background()
      // 本地文件完整路径,例如usr/local/testfile.txt
      fileName = "/usr/local/testfile.txt"
   )
   // 初始化客户端
   client, err := tos.NewClientV2(endpoint, tos.WithRegion(region), tos.WithCredentials(tos.NewStaticCredentials(accessKey, secretKey)))
   checkErr(err)
   // 设置请求方法,桶对象名称,过期时间
   respTempUrl,errURL:=client.PreSignedURL(&tos.PreSignedURLInput{
         HTTPMethod: enum.HttpMethodGet,
         Bucket: bucketName,
         Key: objectKey,
         Expires: 3600,
   })

   checkErr(errURL)
   fmt.Println(respTempUrl.SignedUrl)
}

步骤二:客户端请求发送

本文以 Browser.js 代码为例,介绍如何在客户端发送请求。

注意

使用 Web 端开发过程中,设置跨域资源共享(CORS),具体操作,请参见跨域访问设置

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
$(document).ready(function(){
const Url='https://jsonplaceholder.typicode.com/posts'
    $('.btn').click(function(){
        $.ajax({
            url: Url,
            type: "GET"
            success: function(result){
            console.log(result)
        },
        error:function(error){
        console.log(`Error ${error}`)
        }
        })
    })
 })