本文主要介绍如何基于STS Policy的使用规则在30分钟内搭建一个移动应用数据直传服务。直传指的是移动应用数据的上传和下载直接连接OSS,只有控制流连接自己的服务器。

背景

在移动互联的时代,手机app上传的数据越来越多。作为开发者,您可以利用OSS处理各种数据存储需求,从而更加专注于自己的应用逻辑。

基于OSS的移动应用数据直传服务具有以下优势:
  • 数据安全:使用灵活的授权和鉴权方式进行数据的上传和下载,更加安全。
  • 成本低廉:您不需要准备很多服务器。移动应用直接连接云存储OSS,只有控制流连接应用服务器。
  • 高并发:支持海量用户并发访问。
  • 弹性扩容:无限扩容的存储空间。
  • 数据处理:和图片处理以及音视频转码搭配使用,方便灵活地进行数据处理。

下载并安装移动应用

移动应用源码的下载地址如下:

您可以通过此移动应用上传图片到OSS。上传的方法支持普通上传和断点续传上传。在网络环境差的情况下,推荐使用断点续传上传。您还可以利用图片处理服务,对要上传的图片进行缩略和加水印处理。示例应用的最终效果图如下:



  • 应用服务器:该移动应用对应的后台应用服务器。请使用步骤2:下载应用服务器代码示例中提供的应用服务器代码示例,部署自己的应用服务器。
  • 上传Bucket:该移动应用要把数据上传到哪个Bucket。
  • 区域:上传Bucket所在的地域。

原理介绍

移动应用直传服务的开发流程图如下:

角色分析如下:
  • Android/iOS 移动应用:即最终用户手机上的app,负责从应用服务器申请及使用STS凭证。
  • OSS:即阿里云对象存储,负责处理移动应用的数据请求。
  • RAM/STS:负责生成临时上传凭证,即Token。
  • 应用服务器:即提供该Android/iOS应用的开发者开发的app后台服务,用于管理app上传和下载的Token,以及用户通过app上传数据的元信息。

实现步骤如下:

  1. 移动应用向应用服务器申请一个临时上传凭证。
    说明 Android和iOS应用不能直接存储AccessKey,这样会存在数据泄露的风险。所以应用必须向用户的应用服务器申请一个Token。这个Token是有时效性的,如果Token的过期时间是30分钟(由应用服务器指定),那么在这30分钟里,该Android/iOS应用可以使用此Token从OSS上传和下载数据, 30分钟后需要重新获取Token。
  2. 应用服务器检测上述请求的合法性,然后返回Token给移动应用。
  3. Android/iOS移动应用使用此Token将数据上传到OSS,或者从OSS下载数据。

以下介绍应用服务器如何生成Token以及Android/iOS移动应用如何获取Token。

步骤1:创建Bucket并开通STS服务

  1. 开通OSS,并且创建Bucket
  2. 开通STS服务。
    1. 登录OSS管理控制台
    2. 在OSS概览页中找到基础配置区域,单击安全令牌


    3. 进入到安全令牌快捷配置页面,单击开始授权
      说明 如果没有开通RAM,会弹出开通的对话框。单击 开通。开通完成后单击 开始授权
    4. 系统进行自动授权。请保存AccessKeyID、AccessKeySecret和RoleArn三个参数。
      • 如果您未创建过AccessKey,系统自动创建AccessKey。请保存AccessKeyId、AccessKeySecret和RoleArn,如下图所示。


      • 如果您之前已经创建过AccessKey,也可以单击如下图所示的查看创建新的AccessKey。

步骤2:下载应用服务器代码示例

步骤3:修改配置文件

以下例子采用PHP编写。每个语言的示例代码下载后,都会有一个配置文件config.json,如下所示:
{
"AccessKeyID" : "",
"AccessKeySecret" : "",
"RoleArn" : "",
"TokenExpireTime" : "900",
"PolicyFile": "policy/all_policy.txt"
}
相关参数说明如下:
  • AccessKeyID:填写之前记录的AccessKeyID。
  • AccessKeySecret:填写之前记录的AccessKeySecret。
  • RoleArn:填写之前记录的RoleArn。
  • TokenExpireTime:指Android/iOS应用获取到的Token的失效时间,最小值和默认值均为900s。
  • PolicyFile:该Token所拥有的权限列表的文件,可使用默认值。
    说明

    代码示例中提供了三种最常用的Token权限文件,位于policy目录下面。分别是:

    • all_policy.txt:指定该Token拥有该账号下的所有权限,包括:
      • 创建Bucket
      • 删除Bucket
      • 上传文件
      • 下载文件
      • 删除文件
    • bucket_read_policy.txt:指定该Token拥有该账号下指定Bucket的读权限。
    • bucket_read_write_policy.txt:指定了该Token拥有该账号下指定Bucket的读写权限。
    如果您想要指定该Token只对指定的Bucket有读写权限, 请把bucket_read_policy.txt和bucket_read_write_policy.txt文件里的$BUCKET_NAME替换成指定的Bucket名称。

步骤4:运行示例代码

代码示例的运行方法如下:
  • 对于PHP版本,将包下载解压后,修改config.json文件,直接运行php sts.php即能生成Token,将程序部署到指定的应用服务器地址。
  • 对于Java版本(依赖于java 1.7),将包下载解压后,修改config.json文件,重新打包并运行java -jar app-token-server.jar (port)。如果不指定port(端口),直接运行java -jar app-token-server.jar,程序会监听7080端口。

返回的数据格式解析如下:

//正确返回
{
    "StatusCode":200,
    "AccessKeyId":"STS.3p***dgagdasdg",
    "AccessKeySecret":"rpnwO9***tGdrddgsR2YrTtI",
   "SecurityToken":"CAES+wMIARKAAZhjH0EUOIhJMQBMjRywXq7MQ/cjLYg80Aho1ek0Jm63XMhr9Oc5s˙∂˙∂3qaPer8p1YaX1NTDiCFZWFkvlHf1pQhuxfKBc+mRR9KAbHUefqH+rdjZqjTF7p2m1wJXP8S6k+G2MpHrUe6TYBkJ43GhhTVFMuM3BZajY3VjZWOXBIODRIR1FKZjIiEjMzMzE0MjY0NzM5MTE4NjkxMSoLY2xpZGSSDgSDGAGESGTETqOio6c2RrLWRlbW8vKgoUYWNzOm9zczoqOio6c2RrLWRlbW9KEDExNDg5MzAxMDcyNDY4MThSBTI2ODQyWg9Bc3N1bWVkUm9sZVVzZXJgAGoSMzMzMTQyNjQ3MzkxMTg2OTExcglzZGstZGVtbzI=",
   "Expiration":"2017-12-12T07:49:09Z",
}
//错误返回
{
    "StatusCode":500,
    "ErrorCode":"InvalidAccessKeyId.NotFound",
    "ErrorMessage":"Specified access key is not found."
}
正确返回的五个变量构成一个Token:
  • StatusCode:获取Token的状态,获取成功时,返回值是200。
  • AccessKeyId:Android/iOS移动应用初始化OSSClient获取的 AccessKeyId。
  • AccessKeySecret:Android/iOS移动应用初始化OSSClient获取AccessKeySecret。
  • SecurityToken:Android/iOS移动应用初始化的Token。
  • Expiration:该Token失效的时间。Android SDK会自动判断Token是否失效,如果失效,则自动获取Token。
错误返回说明如下:
  • StatusCode:表示获取Token的状态,获取失败时,返回值是500。
  • ErrorCode:表示错误原因。
  • ErrorMessage:表示错误的具体信息描述。

步骤5:体验移动应用直传服务

  1. 部署程序后,记下应用服务器地址如http://abc.com:8080,将示例程序里面的应用服务器修改成上述地址。
  2. 选择数据要上传到哪个Bcuket及地域,修改示例程序里相应的上传Bucket区域
  3. 单击设置,加载配置。
  4. 选择图片,设置上传OSS文件名,上传图片。
  5. 上传成功后,通过控制台查看上传结果。

核心代码解析

OSS初始化的代码解析如下:

  • Android版本
    // 推荐使用OSSAuthCredentialsProvider,token过期后会自动刷新。
    String stsServer = "应用服务器地址,例如http://abc.com:8080"
    OSSCredentialProvider credentialProvider = new OSSAuthCredentialsProvider(stsServer);
    //config
    ClientConfiguration conf = new ClientConfiguration();
    conf.setConnectionTimeout(15 * 1000); // 连接超时时间,默认15秒
    conf.setSocketTimeout(15 * 1000); // Socket超时时间,默认15秒
    conf.setMaxConcurrentRequest(5); // 最大并发请求数,默认5个
    conf.setMaxErrorRetry(2); // 失败后最大重试次数,默认2次
    OSS oss = new OSSClient(getApplicationContext(), endpoint, credentialProvider, conf);
  • iOS版本
    OSSClient * client;
    ...
    // 推荐使用OSSAuthCredentialProvider,token过期后会自动刷新。
    id<OSSCredentialProvider> credential = [[OSSAuthCredentialProvider alloc] initWithAuthServerUrl:@"应用服务器地址,例如http://abc.com:8080"];
    client = [[OSSClient alloc] initWithEndpoint:endPoint credentialProvider:credential];