zoukankan      html  css  js  c++  java
  • 30分钟快速搭建移动应用直传OSS服务

    30分钟快速搭建移动应用直传服务

    背景

    这是一个移动互联的时代。手机APP上传的数据会越来越多。把数据存储的问题交给OSS, 让开发者能更加专注于自己的应用逻辑。
    那么怎么样基于OSS构建一个APP存储系统呢?

    目的

    本教程就是让你在30分钟内搭建一个基于OSS的移动应用数据直传服务,所谓直传就是移动应用的数据的上传和下载直接直连OSS,只有控制流走用户自己的服务器。

    1. 安全的上传下载方式(临时,灵活的赋权鉴权),
    2. 成本低(这样用户不需要准备很多服务器,因为移动应用直联云存储,只有控制流走用户自己的应用服务器。)
    3. 高并发,支持海量用户(OSS有海量的上传和下载带宽)
    4. 弹性(OSS有无限扩容的存储空间)
    5. 方便(可以方便的对接到媒体转码服务-视频多端适配,图片处理服务,CDN加速下载等)

    架构图

    本教程就是让你在30分钟内搭建一个基于OSS的移动应用数据直传服务

    详细可以参考这里

    角色解析

    1. Android/iOS 应用。即最终用户手机上的APP;
    2. OSS,即阿里云对象存储,负责存储APP上传的数据,可以参考官网http://www.aliyun.com/product/oss;
    3. RAM/STS负责生成临时上传凭证
    4. 用户应用服务器,即提供该Android/iOS应用的开发者开发的APP后台服务,管理APP上传和下载的Token. 甚至是用户在APP上传数据元数据信息。

    数据流解析

    1. Android/iOS应用不可能直接存储AccessKeyID/AccessKeySecret,这样会存在泄密的风险。所以应用必须向用户的应用服务器申请一个临时上传凭证(注意下文将此临时上传凭证称为Token),注意这个Token是有时效性的,如这个Token的过期时间是30分钟(这个时间可以由应用服务器指定),那么在该Android/iOS应用在这30分钟里面,使用这个Token可以从OSS上传和下载数据, 30分钟后再重新获取。
    2. 用户的应用服务器检测上述请求的合法性,然后返回Token给应用。
    3. 手机拿到这个Token后就可以将数据上传到OSS,或者从OSS下载数据了。

    本教程的目的就是,介绍下述红色和蓝色框的内容

    1. 应用服务器如何生成这个Token,蓝色方框
    2. Android/iOS应用如何取Token,红色方框

    效果

    本教程实现了一个APP,如下,大家可以扫描二维码,安装一下示例APP程序,这上工具是用Android开发。 但是本教程的应用服务器搭建也适用于iOS, 即上述图蓝色的框的内容。

    示例程序的体验

    示例程序的最终效果图如下:

    1. 应用服务器:该移动应用对应的后台应用服务器。本教程搭建了一个后台应用服务器:http://oss-demo.aliyuncs.com/app-server/sts.php

    2. 上传Bucket,指的是该移动应用要把数据上传到哪个Bucket

    3. 区域:指的第二步指定的Bucket对应的区域。

    示例APP的使用

    可以点击选择图片,然后就把文件上传到OSS,上传的方法,支持普通上传和断点上传。注意在一些网络环境差的环境下,最好用断点上传。然后可以利用图片处理服务,可以对将上传的图片进行缩略和加水印处理。初始使用请暂时先不要改应用服务器地址和Bucket名字
    

    搭建这样一个APP上传和下载的系统 ,需要准备的东西:

    1. 我必须开通了OSS,并且创建了Bucket, 在这个例子里面的,对应的bucket是 :sdk-demo
    2. 我必须开通STS服务。开通STS服务其实是为了如何生成上述所描述的Token
    3. 我必须搭建这样一个应用服务器。这在个事例里面,我搭建的应用服务器的地址是:http://oss-demo.aliyuncs.com/app-server/sts.php .
      注意这个例子本教程是采用PHP编写的,但是事实上,用户可以选择自己喜欢的语言进行编写,如Java 、Python、 Go、Ruby、Node.js、C#等编写

    为帐号开通STS服务

    1. 如果已经有bucket可以忽略这一步, 如果没有bucket,创建Bucket参考官网

    2. 第二步操作,开通STS,可以参考 如下:
      (1)要开通STS服务,首先OSS登陆官网控制台

    (2)登录管理控制台,点击:安全令牌快捷配置

    (3)会进入到令牌快捷配置页面,注意如果没有开通RAM,会弹出开通的对话框。直接点开通,这个要求实名验证。 做完后跳到本页面。点击开始授权

    (4)点击开始授权后,系统会进行自动授权,请千万保存如下图框住的三个参数

    点击保存AK信息后,对话框会关闭。保存好下面标红的结果3.

    保存这三个参数后。到这一步,STS的开通已经完成了。
    注意如果您之前已经点击这个页面创建了AccessKeyId/AccessKeySecrte, 弹出的页面如下:

    点击如下图所示的查看

    点击如下图所示的创建AccessKey

    记下如下参数1,2

    并记下如下参数3:

    保存这三个参数后。到这一步,STS的开通已经完成了。

    讲解一下应用服务器的搭建。

    为了方便大家开发。 本教程准备了三个语言的版本示例程序 (Java、PHP、Ruby)

    应用服务器代码示例的下载

    PHP: 下载地址

    Java: 下载地址

    Ruby: 下载地址

    应用服务器示例的配置

    每个语言包下载下来后,都会有一个配置文件config.json
    如下例:

    {
    "AccessKeyID" : "",
    "AccessKeySecret" : "",
    "RoleArn" : "",
    "TokenExpireTime" : "900",
    "PolicyFile": "policy/all_policy.txt"
    }
    

    下面对配置进行讲解。

    1. AccessKeyID填写上述图标红的1的内容,即用户自己在全
    2. AccessKeySecret填写上述图片标红2的内容
    3. RoleArn 填写上述图标红3的内容
    4. TokenExpireTime 指Android/iOS应用取到这个Token的失效时间,注意,最少是900s, 默认值可以不修改,
    5. 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名字。

    返回的格式解析 。

    {
        "status":200,
        "AccessKeyId":"STS.3pYjsdgdgagdasdg",
        "AccessKeySecret":"rpnwO9kvEgetGdrddgsR2YrTtI",
        "Security":"CAES+wMIARKAAZhjH0EUOIhJMQBMjRywXq7MQ/cjLYg80Aho1ek0Jm63XMhr9Oc5s˙∂˙∂3qaPer8p1YaX1NTDiCFZWFkvlHf1pQhuxfKBc+mRR9KAbHUefqH+rdjZqjTF7p2m1wJXP8S6k+G2MpHrUe6TYBkJ43GhhTVFMuM3BZajY3VjZWOXBIODRIR1FKZjIiEjMzMzE0MjY0NzM5MTE4NjkxMSoLY2xpZGSSDgSDGAGESGTETqOio6c2RrLWRlbW8vKgoUYWNzOm9zczoqOio6c2RrLWRlbW9KEDExNDg5MzAxMDcyNDY4MThSBTI2ODQyWg9Bc3N1bWVkUm9sZVVzZXJgAGoSMzMzMTQyNjQ3MzkxMTg2OTExcglzZGstZGVtbzI=",
       "Expiration":"2015-12-12T07:49:09Z",
    }
    
    

    status:表示获取Token的状态,获取成功时,返回值是200
    AccessKeyId: 表示Android/iOS应用初始化OSSClient获取的 AccessKeyId
    AccessKeySecret: 表示Android/iOS应用初始化OSSClient获取AccessKeySecret
    SecurityToken:表示Android/iOS应用初始化的Token
    Expiration: 表示该Token失效的时间。主要在Android SDK会自动判断是否失效,自动获取Token
    注意上述这四个变量将构成了一个Token。

    代码示例的运行方法

    对于PHP版本

    PHP运行的,将包下载 后,然后修改好config.json这个文件。直接运行php sts.php 即能生成Token,将程序部署到指定的地址。
    
    

    对于JAVA版本 (依赖于java 1.7)

    下载编译好的jar 包,下载地址: 
    下载后解压:
    运行方法:java  -jar oss-token-server.jar (port)
    如果不指定port(端口), 直接运行java –jar  oss-token-server.jar , 程序会监听7080端口
    如果想让程序执行在9000端口,运行java –jar oss-token-server.jar 9000 , 其他端口也类似。
    
    

    体验自己的APP上传应用服务器

    
    1. 把把程序部署起来后,记下应用服务器地址如 :http://abc.com:8080, 将示例程序里面的应用服务器修改成上述地址
    
    2. 选择自己数据要上传到哪个bcuket及区域,修改示例APP程序里面相应Bucket及区域。
    
    3. 点击设置按钮,将配置加载。
    
    4. 选择图片,设置上传OSS文件名,上传。然后就可以在Android上体验OSS服务了。这样你就能通Android 示例程序将数据直接上传到OSS了 
    
    5. 上传成功后,可以看一下数据是否在OSS上了
    
    

    核心代码解析-OSS初始化

    下面讲解一下如何 利用Android/iOS SDK跟自己的应用服务器,请求Token

    • Android版本
    //初始化一个OssService用来上传下
    public OssService initOSS(String endpoint, String bucket, UIDisplayer displayer) {
        OSSCredentialProvider credentialProvider;
        //使用自己的获取STSToken的类
    //从应用服务器控件里面读取应用服务器地址
        String stsServer = ((EditText) findViewById(R.id.stsserver)).getText().toString();
        //STSGetter类,封装如何跟从应用服务器取数据,必须继承于OSSFederationCredentialProvider这个类。 取Token这个取决于你所写的APP跟应用服务器数据的协议设计。
        if (stsServer .equals("")) {
            credentialProvider = new STSGetter();
        }else {
            credentialProvider = new STSGetter(stsServer);
        }
    //获取控件上的bucket名字
        bucket = ((EditText) findViewById(R.id.bucketname)).getText().toString();
    
    //初始化OSSClient 
        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);
        return new OssService(oss, bucket, displayer);
    }
    
    • iOS版本
    
    // 初始化一个OSSClient实例
    - (void)ossInit {
    	// 构造一个获取STSToken的凭证提供器
        id<OSSCredentialProvider> credential = [[OSSFederationCredentialProvider alloc] initWithFederationTokenGetter:^OSSFederationToken * {
        	// 实现一个函数,同步返回从server获取到的STSToken
            return [self getFederationToken];
        }];
        
        // 用endpoint、凭证提供器初始化一个OSSClient
        client = [[OSSClient alloc] initWithEndpoint:endPoint credentialProvider:credential];
    }
    

    核心代码解析-移动应用从应用服务器取Token

    具体APP从就应用服务器取Token方法,必须写到public OSSFederationToken getFederationToken() { } 这个函数里面。
    注意这个函数的逻辑依赖于可以自己设定,但是最终结果必须返回这样一个变量 return new OSSFederationToken(ak, sk, token, expiration);
    其中ak, sk, token, expiration 必须是从应用服务器返回的Body获取的。

    在本例子里,示例如下,注意用户可以自定义自己的移动应用跟自己应用服务器之前的协议。

    • Android版本
    public OSSFederationToken getFederationToken() {
        String stsJson;
        OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder().url(stsServer).build();
        try {
            Response response = client.newCall(request).execute();
            if (response.isSuccessful()) {
                stsJson = response.body().string();
            } else {
                throw new IOException("Unexpected code " + response);
            }
        }
        catch (IOException e) {
            e.printStackTrace();
            Log.e("GetSTSTokenFail", e.toString());
            return null;
        }
    
        try {
            JSONObject jsonObjs = new JSONObject(stsJson);
            String ak = jsonObjs.getString("AccessKeyId");
            String sk = jsonObjs.getString("AccessKeySecret");
            String token = jsonObjs.getString("SecurityToken");
            String expiration = jsonObjs.getString("Expiration");
            return new OSSFederationToken(ak, sk, token, expiration);
        }
        catch (JSONException e) {
            Log.e("GetSTSTokenFail", e.toString());
            e.printStackTrace();
            return null;
        }}
    
    • iOS版本
    
    NSURL * url = [NSURL URLWithString:STSServer];
    NSURLRequest * request = [NSURLRequest requestWithURL:url];
    OSSTaskCompletionSource * tcs = [OSSTaskCompletionSource taskCompletionSource];
    NSURLSession * session = [NSURLSession sharedSession];
    NSURLSessionTask * sessionTask = [session dataTaskWithRequest:request
                                                completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
                                                    if (error) {
                                                        [tcs setError:error];
                                                        return;
                                                    }
                                                    [tcs setResult:data];
                                                }];
    [sessionTask resume];
    
    // 实现这个回调需要同步返回Token,所以要waitUntilFinished
    [tcs.task waitUntilFinished];
    
    if (tcs.task.error) {
        // 如果网络请求出错,返回nil表示无法获取到Token。该次请求OSS会失败。
        return nil;
    } else {
        // 从网络请求返回的内容中解析JSON串拿到Token的各个字段,组成STSToken返回
        NSDictionary * object = [NSJSONSerialization JSONObjectWithData:tcs.task.result
                                                                options:kNilOptions
                                                                  error:nil];
        OSSFederationToken * token = [OSSFederationToken new];ni
        token.tAccessKey = [object objectForKey:@"AccessKeyId"];
        token.tSecretKey = [object objectForKey:@"AccessKeySecret"];
        token.tToken = [object objectForKey:@"SecurityToken"];
        token.expirationTimeInGMTFormat = [object objectForKey:@"Expiration"];
        
        return token;
    }
    
    

    OSS相关功能的代码,可以查看示例程序的实现

    该Android示例程序的源码下载地址

    该iOS示例程序的源码下载地址

    应用服务器代码示例的下载

    PHP: 下载地址

    Java: 下载地址

    Ruby: 下载地址

  • 相关阅读:
    D. Babaei and Birthday Cake--- Codeforces Round #343 (Div. 2)
    Vijos P1389婚礼上的小杉
    AIM Tech Round (Div. 2) C. Graph and String
    HDU 5627Clarke and MST
    bzoj 3332 旧试题
    codeforces 842C Ilya And The Tree
    codesforces 671D Roads in Yusland
    Travelling
    codeforces 606C Sorting Railway Cars
    codeforces 651C Watchmen
  • 原文地址:https://www.cnblogs.com/ossteam/p/5059571.html
Copyright © 2011-2022 走看看