背景

モバイルインターネットの時代において、モバイルアプリはより多くのデータをアップロードしています。 データストレージの問題を OSS に引き渡すことで、開発者は自分のアプリロジックにより集中することができるようになります。

この記事では、30 分でモバイルアプリの OSS ベースの直接データ転送サービスを設定する方法について説明します。 直接データ転送は、モバイルアプリが OSS に直接接続されている間、制御トラフィックをアプリサーバーに送信、データをアップロードおよびダウンロードするサービスです。

利点

モバイルアプリに OSS ベースの直接データ転送サービスを設定すると、次のような利点があります。

  • より安全なアップロードとダウンロード方法 (一時的かつ柔軟な許可の割り当てと認証)。
  • 低価格。 アプリサーバーの少数化。 モバイルアプリはクラウドストレージに直接接続されており、制御トラフィックのみがアプリサーバーに送信されます。
  • 高い同時実行性と大量のユーザーのサポート (OSS はアップロードとダウンロードのため、大きな帯域幅を提供しています)。
  • 高い弾力性 (OSS のストレージスペースは無制限に拡張できます)。
  • 利便性。 MTS -video マルチポートアダプタ、Image Service、CDN ダウンロードアクセラレーション、およびその他のサービスに簡単に接続できます。

アーキテクチャダイアグラムは次のとおりです。



詳細:

  • Android/iOS mobile app。エンドユーザーの携帯電話にインストールされているアプリです。
  • OSS。Alibaba Cloud Object Storage Service の略で、アプリがアップロードしたデータを保存します。 詳しくは、Alibaba Cloud Web サイト内の「OSS description on Alibaba Cloud website」をご参照ください。
  • 一時的なアクセス認証情報を生成する RAM と STS。
  • Android / iOS モバイルアプリ用に開発されたバックグラウンドサービスで、アプリによるデータのアップロードとダウンロードに使用されるトークンと、アプリでアップロードされたデータのメタデータを管理するために使用されます。

ステップ:

  1. アプリサーバーからの一時的なアップロード認証情報を要求します。

    Android / iOS アプリは、AccessKeyID と AccessKeySecret を直接保存できないため、情報漏洩の危険性があります。 そのため、アプリはアプリサーバーから一時的なアップロード認証情報 (トークン) を要求する必要があります。 トークンは一定期間のみ有効です。 たとえば、トークンが 30 分間有効 (アプリケーションサーバーで編集可能) に設定されている場合、Android / iOS アプリは、 このトークンを使用して30 分間だけ、 OSS との間でデータをアップロードまたはダウンロードできます。 30 分経つと、アプリはデータをアップロードおよびダウンロードするため、新しいトークンを要求する必要があります。

  2. アプリサーバーは、前のリクエストの有効性を確認してから、トークンをアプリに返します。
  3. 携帯電話はこのトークンを受信した後、OSS からデータをアップロードまたはダウンロードできます。

この記事では、主に次の図の赤い円と青い円の中身について説明します。



  • 青い円は、アプリサーバーがトークンを生成する方法を示しています。
  • 赤い円は、Android / iOS アプリが、トークンを受け取る方法を示しています。

直接データ転送サービスをセットアップするための前提条件

直接データ転送サービスをセットアップするための前提条件:

  1. OSS サービスをアクティブにし、バケットを作成
  2. STS サービスをアクティブにする。
    1. OSS コンソール」にログインします。
    2. 次の図に示すように、[OSS の概要] ページで [基本設定] フィールドを見つけ、[セキュリティトークン] をクリックします。

    3. [クイックセキュリティトークン設定] ページに入ります。
      RAM がまだアクティブになっていない場合は、RAM をアクティブにするためのプロンプトボックスが表示されます。 [アクティブにする] をクリックして、実名検証を実行します。 検証が終わると、次のページが表示されます。 [承認開始] をクリックします。


    4. システムは自動的に承認を実行します。 次の図の 3 つの赤いボックスにパラメーターを保存します。 [アクセスキー情報の保存 ] をクリックしてダイアログボックスを閉じ、STS のアクティブ化を完了します。


    5. AccessKeyId および AccessKessKeySecret をすでに作成している場合は、次のプロンプトウィンドウが表示されます。

      • 次の図に示すように、[表示] をクリックします。

      • 次の図に示すように、[アクセスキーの作成] をクリックします。

      • 次の図に示すように、パラメーター 1、2、および 3 を記録します。


      • 3 つのパラメータを保存したら、STS の有効化は完了です。

アプリサーバーの設定

サンプルアプリサーバーの設定
この例のアプリは PHP で書かれています。 アプリは好みの言語で書くことができます。 Java、Python、Go、Ruby、Node.js、C# 等。

このチュートリアルでは、多言語でダウンロードできる開発サンプルプログラムを提供しています。 ダウンロードアドレスはこの記事の最後にあります。

各言語のダウンロードパッケージには、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 アプリによって取得されたトークンの有効期限を示します。 最小値は 900 秒です。 既定値は保持することができます。
    5. PolicyFile: トークンが付与する権限を列挙したファイルを示します。 既定値を保持することができます。

このドキュメントではポリシーディレクトリで、最も一般的な許可を定義する 3 つのトークンファイルを提供しています。 3 つのトークンファイル:

  • all_policy.txt: このアカウントのバケットを作成または削除する権限を付与するトークンを指定します。また、ファイルをアップロード、ダウンロード、または削除する権限を付与するトークンを指定します。
  • bucket_read_policy.txt: このアカウントに対して指定されたバケットを読み取るための許可を与えるトークンを指定します。
  • bucket_read_write_policy.txt: このアカウントに対して指定されたバケットの読み書きを許可するトークンを指定します。

指定したバケットに対する読み取りおよび書き込み権限を付与するトークンを作成する場合は、"bucket_read_policy.txt" ファイルおよび"bucket_read_write_policy.txt" ファイルの "$ BUCKET_NAME" を指定したバケットの名前に置き換えます。

  • 返されるデータフォーマットの説明
    //Correct result returned
    {
        "statusCode": "20"、
        "AccessKeyId":"STS. 3p***dgagdasdg",
        "AccessKeySecret":"rpnwO9***tGdrddgsR2YrTtI",
       "SecurityToken":"CAES+wMIARKAAZhjH0EUOIhJMQBMjRywXq7MQ/cjLYg80Aho1ek0Jm63XMhr9Oc5s˙∂˙∂3qaPer8p1YaX1NTDiCFZWFkvlHf1pQhuxfKBc+mRR9KAbHUefqH+rdjZqjTF7p2m1wJXP8S6k+G2MpHrUe6TYBkJ43GhhTVFMuM3BZajY3VjZWOXBIODRIR1FKZjIiEjMzMzE0MjY0NzM5MTE4NjkxMSoLY2xpZGSSDgSDGAGESGTETqOio6c2RrLWRlbW8vKgoUYWNzOm9zczoqOio6c2RrLWRlbW9KEDExNDg5MzAxMDcyNDY4MThSBTI2ODQyWg9Bc3N1bWVkUm9sZVVzZXJgAGoSMzMzMTQyNjQ3MzkxMTg2OTExcglzZGstZGVtbzI=",
       "Expiration":"2015-12-12T07:49:09Z",
    }
    //Wrong result returned
    {
        "statusCode": "20"、
        "ErrorCode":"InvalidAccessKeyId.NotFound",
        "ErrorMessage":"Specified access key is not found."
    }
    返された正しい結果の説明: (次の 5 つの変数がトークンを構成します)
    • StatusCode: ステータスは、アプリがトークンを取得した結果を示します。 トークンの取得に成功すると、アプリは "200" を返します。
    • AccessKeyId: OSS クライアントを初期化するときに Android / iOS アプリが取得する "AccessKeyId" を示します。
    • AccessKeySecret: OSS クライアントを初期化するときに Android / iOS アプリが取得する "AccessKeySecret" を示します。
    • SecurityToken: Android / iOS アプリが初期化するトークンを示します。
    • Expiration: トークンの有効期限が切れる時刻を示します。Android SDK は自動的にトークンの有効性を判断し、必要に応じて新しいものを取得します。
    返された誤った結果の説明:
    • StatusCode: ステータスは、アプリがトークンを取得した結果を示します。 トークンの取得に失敗した場合、アプリは "500" を返します。
    • ErrorCode: エラーの原因を示します。
    • ErrorMessage: エラーに関する詳細情報を示します。
  • サンプルコードの実行方法:
    • PHP の場合は、パックをダウンロードして解凍し、"config.json" ファイルを変更して "php sts.php" を実行してトークンを生成し、指定されたアドレスにプログラムをデプロイします。

    • Java (Java 1.7ベース) の場合、パックをダウンロードして解凍した後、以下のコマンドを実行します。java -jar oss-token-server.jar(port)

      ポートを指定せずに java –jar oss-token-server.jar を実行すると、プログラムは Port 7080 をリッスンします。 リスニングポートを 9000 に変更するには、java –jar app-token-server.jar 9000 を実行します。 必要に応じて、ポート番号を指定します。

アプリから OSS にファイルをアップロードする方法

  1. アプリケーションサーバーを設定したら、サーバーアドレス (http://abc.com:8080) を書き留めます。 次に、サンプルプロジェクトのアプリケーションサーバーアドレスをこのアドレスに置き換えます。
  2. サンプルアプリでアップロードするバケットとリージョンを指定します。
  3. [設定]をクリックし、設定を読み込みます。
  4. 画像ファイルを選択し、OSS にアップロードするオブジェクト名を設定して、アップロードを選択します。 これで Android 上で OSS サービスを体験することができます。 Android アプリからのデータは OSS に直接アップロードできます。
  5. アップロードが完了したら、データが OSS 上にあることを確認します。

コアコードの説明

OSS の初期化

以下は、Android / iOS SDK を使用し、アプリケーションサーバーからトークンを要求する方法を説明しています。

  • Android バージョン
    //Initialize an OssService for upload and download.
    public OssService initOSS(String endpoint, String bucket, UIDisplayer displayer) {
        OSSCredentialProvider credentialProvider;
        //Use your own class to retrieve an STSToken.
    //Read the server address from app server controls.
        String stsServer = ((EditText) findViewById(R.id.stsserver)).getText().toString();
        //STSGetter class, encapsulating the way of retrieving data from the app server, must be inherited from the class OSSFederationCredentialProvider. The way that your app retrieves tokens depends on the protocol between the app and the app server.
        if (stsServer .equals("")) {
            credentialProvider = new STSGetter();
        } else{
            credentialProvider = new STSGetter(stsServer);
        }
    //Retrieve the bucket name from the controls.
        bucket = ((EditText) findViewById(R.id.bucketname)).getText().toString();
    //Initialize an OSSClient. 
        ClientConfiguration conf = new ClientConfiguration();
        conf.setConnectionTimeout(15 * 1000); // Connection time-out.  The default value is 15 seconds.
        conf.setSocketTimeout(15 * 1000); // Socket time-out. The default value is 15 seconds.
        conf.setMaxConcurrentRequest(5); // The maximum number of concurrent requests. The default value is 5.
        conf.setMaxErrorRetry(2); // The maximum number of retry attempts after each failed attempt. The default value is 2.
        OSS oss = new OSSClient(getApplicationContext(), endpoint, credentialProvider, conf);
        return new OssService(oss, bucket, displayer);
    }
  • iOS バージョン
    //Initialize an OSSClient instance.
    - (void)ossInit {
        //Construct a credential provider for retrieving STSTokens.
        id<OSSCredentialProvider> credential = [[OSSFederationCredentialProvider alloc] initWithFederationTokenGetter:^OSSFederationToken * { 
            //Implement a function to synchronize the STSToken retrieved from the server.
            return [self getFederationToken];
        }];
        //Use endpoint and the credential provider to initialize an OSSClient.
        client = [[OSSClient alloc] initWithEndpoint:endPoint credentialProvider:credential];
    }

モバイルアプリのアプリサーバーからトークンを取得

アプリがアプリサーバーからトークンを取得する特定のメソッドは、関数 public OSSFederationToken getFederationToken() { } に書き込む必要があります。}
この関数のロジックを定義できますが、返されるメッセージには以下の変数が含まれている必要があります。return new OSSFederationToken(ak, sk, token, expiration). ここで、"ak"、"sk"、"token"、および "expiration" は、サーバーから返されたメッセージの本文から取得する必要があります。

この例では、アプリとアプリサーバーをリンクするプロトコルを指定します。

  • 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 (SQLException 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];
    // Implementation of this callback must be synchronized with the returned token, so the task waitUntilFinished is necessary.
    [tcs.task waitUntilFinished];
    if (tcs.task.error) {
        // If the network request fails, the return of nil indicates the token cannot be retrieved. In this case, this OSS request fails.
        return nil;
    } else{
        // Parse the JSON string returned to the network request to get each token field and return an 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;
    }

ソースコードのダウンロード

プログラムの例
アプリサーバーのサンプルコードのダウンロード