快速搭建移动应用传输服务

最近更新时间: 2024-10-17 17:10:00

背景

移动互联网时代,App 作为移动互联网服务的基础设施,往往需要上传和下载大量的数据,数据的安全性和可靠性尤为重要。现在开发者可以将数据存储相关的问题交给 云平台 COS 服务,而只需要关心自己应用的业务逻辑即可,可减少很多工作量,提升开发效率。

本文主要介绍如何快速搭建一个基于 COS 的应用传输服务,在云平台 COS 上实现应用数据的上传下载,在您的服务器上只需要部署您自己的业务、生成和管理临时密钥。

架构

整体架构图如下所示:

其中:

  • 应用 APP:即用户手机上的 App。

  • COS:云平台对象存储,负责存储 App 上传的数据。

  • CAM:云平台访问管理,用于生成 COS 的临时密钥。

  • 应用服务器:用户自己的后台服务器,这里用于向 CAM 请求临时密钥,并返回给应用 App。

步骤

  1. 应用向用户的应用服务器发送一个获取临时密钥的请求。 用户 App 在向 COS 发送请求时,必须通过密钥对请求进行签名。直接将用户的永久密钥放在终端上会存在很大的泄密风险,因此必须将您的永久密钥放在您的应用服务器上,然后由应用服务器向云平台 CAM 申请临时密钥,并最终返回给终端对请求进行签名。

  2. 应用服务器收到请求后,向 CAM 申请临时密钥。 我们认为用户的应用服务器是可信任的,可以直接配置用户的永久密钥用于向 CAM 申请临时密钥。同时,在服务端您可以配置临时密钥的有效期以及策略(Policy)。

  3. CAM 返回临时密钥给应用服务器。

  4. 应用服务器返回临时密钥给应用 App。 我们对数据的返回格式没有做具体的要求,这里建议直接返回 CAM 的 JSON 数据即可。

  5. 应用 App 向 COS 发送请求(如上传文件等)。 应用 App 获取到临时密钥后,可以通过我们的 SDK 很容易地对请求进行签名,来使用我们的 COS 服务。

示例

搭建一个应用服务器

本示例采用 Python 编写,您可以 点击下载

  1. 配置参数 下载并解压好的文件夹根目录下有config.py目录,可以来配置以下参数:

    class Config(object):
    
     def __init__(self):
         pass
    
     # 用户昵称,非必选
     NAME = "WANG"
     # 策略
     POLICY = COMMON_POLICY
     # 临时证书有效期
     DURATION_SECOND = 1800
     # 用户的secret id
     SECRET_ID = "您的 secret id"
     # 用户的secret key
     SECRET_KEY = "您的 secret key"

    示例中提供的是一个拥有账户下所有资源读写权限的策略。

  2. 解析返回的 JSON 数据

    {
     "code":0,"message":"","codeDesc":"Success",
     "data":
     {
         "credentials":
         {
             "sessionToken":"42f8151428b3960b1226f421b8f271c6242ad02c3",
             "tmpSecretId":"AKIDtd9QSGWBIDuMaYFp57tSmrhJgohLtvpT",
             "tmpSecretKey":"ZfV5PVLvFLCvPefPt76qKYXIo56tSmrg"
         },
         "expiredTime":1508400619
     }
    }

应用服务器搭建临时密钥服务

下面以云平台 CVM Ubuntu 实例为例,详细介绍如何搭建一个简单的临时密钥服务。

  1. 登录云平台 CVM

    购买 CVM 实例后,可直接用浏览器在控制台登录,或者使用终端直接 SSH 登录。

  2. Ubuntu 环境下配置 Python 开发环境

    sudo apt-get update
    sudo apt-get install python-dev python-pip python-virtualenv
  3. 下载源码并解压

    wget http://rickenwang-1253653367.cosgz.myqcloud.com/resources/signer-release.zip
    unzip signer-release.zip
    ```   > 下载后直接解压,解压后需要修改根目录下的`secret_key`和`secret_id`配置信息,具体值可以在云 API 密钥控制台上查询。
  4. 激活 virtualenv 环境并进行配置

    1. 激活 virtualenv 环境:
    cd 到flask项目目录
    virtualenv venv
    source venv/bin/activate
    1. 配置环境:
    pip install gunicorn
    pip install flask
    pip install flask-script
  5. 使用 supervisor 管理服务

    1. 安装 supervisor 并打开配置文件
    pip install supervisor
    echo_supervisord_conf > supervisor.conf
    vi supervisor.conf
    1. 在配置文件supervisor.conf的底部添加以下内容:
    [program:manage]
    command=./venv/bin/gunicorn -w4 -b0.0.0.0:5000 manage:app    
    directory=./                                              
    startsecs=0   
    stopwaitsecs=0    
    autostart=false                                                                        
    autorestart=false                                                             
    stdout_logfile=./log/gunicorn.log                          
    stderr_logfile=./log/gunicorn.err                     
  6. 启动服务并测试

    使用如下命令启动服务:

    supervisord -c supervisor.conf
    supervisorctl -c supervisor.conf start manage

    应用服务器启动后,直接用浏览器访问http://ip:5000/sign地址,若返回临时密钥 JSON 字符串,则说明应用服务器临时密钥服务正常运行。

注意:

浏览器访问时 IP 请修改为您服务器的 IP 或者域名,默认的端口是 5000,您可自行在supervisor.conf文件中修改。

应用 App 接入应用服务器临时密钥服务

若您对云平台 COS 服务已有一些基本的了解,那么您可以很容易地使用我们 COS XML 终端 SDK,并将您的应用服务器的临时密钥服务接入进来,下面以 Android SDK 为例说明,总共分为三步:

注意:

使用我们的 SDK 前,您需要了解一些基本的名词术语,如 APPID、Bucket、SecretId、SecretKey 等。

1. 定义MySessionCredentialProvider类继承抽象类BasicLifecycleCredentialProvider,并实现其 fetchNewCredentials() 方法。


public class MySessionCredentialProvider extends BasicLifecycleCredentialProvider {

    @Override
    protected QCloudLifecycleCredentials fetchNewCredentials() throws QCloudClientException {

        SessionQCloudCredentials credentials;
        String tempSecretId = "";
        String tempSecretKey = "";
        String sessionToken = "";
        long expireTime;

        // 1、访问应用服务器获取临时密钥 API,获取临时密钥 JSON 字符串
        // ...


        // 2、解析 JSON 字符串,初始化 tempSecretId, tempSecretKey, sessionToken, expiredTime 四个参数
        // ...


        // 3、返回 SessionQCloudCredentials
        return new SessionQCloudCredential(tempSecretId, tempSecreKey, sessionToken, expireTime);

    }

}

2. 用MySessionCredentialProvider初始化CosXmlService

// 您的账户信息
String appid = "对象存储 的服务APPID";
String region = "存储桶 所在的地域";

// 创建 CosXmlServiceConfig 对象
CosXmlServiceConfig serviceConfig = new CosXmlServiceConfig.Builder()
       .setAppidAndRegion(appid, region)
       .build();

// 初始化 CosXmlService
CosXmlService cosXmlService = new CosXmlService(getApplicationContext(), cosXmlServiceConfig,
                    new MySessionCredentialProvider());

3. 通过CosXmlService对象的各种接口访问 COS 服务,下面以简单上传为例:

String bucket = "存储桶名称";
String cosPath = "远端路径,即存储到 COS 上的绝对路径"; //格式如 cosPath = "/test.txt";
String srcPath = "本地文件的绝对路径"; // 如 srcPath = Environment.getExternalStorageDirectory().getPath() + "/test.txt";
long signDuration = 600; //签名的有效期,单位为秒

PutObjectRequest putObjectRequest = new PutObjectRequest(bucket, cosPath, srcPath);

putObjectRequest.setSign(signDuration,null,null);

/*
 * 设置进度显示
 * 实现 QCloudProgressListener.onProgress(long progress, long max) 方法,
 * progress 已上传的大小, max 表示文件的总大小
 */
putObjectRequest.setProgressListener(new QCloudProgressListener() {

    @Override
    public void onProgress(long progress, long max) {
        float result = (float) (progress * 100.0/max);
        Log.w("TEST","progress =" + (long)result + "%");
    }
});

//使用同步方法上传
try {
    PutObjectResult putObjectResult = cosXmlService.putObject(putObjectRequest);
    Log.w("TEST","success: " + putObjectResult.accessUrl);

    } catch (CosXmlClientException e) {
       //抛出异常
       Log.w("TEST","CosXmlClientException =" + e.toString());
    } catch (CosXmlServiceException e) {
       //抛出异常
       Log.w("TEST","CosXmlServiceException =" + e.toString());
}