全部產品
Search
文件中心

Resource Access Management:行動裝置 App使用臨時安全性權杖訪問阿里雲

更新時間:Jun 06, 2025

本文介紹行動裝置 App如何使用RAM角色的臨時安全性權杖(STS Token)訪問阿里雲資源。

背景資訊

企業A開發了一款行動裝置 App(App),併購買了Object Storage Service服務。App需要直連OSS上傳或下載資料,但是App運行在使用者自己的行動裝置上,這些裝置不受企業A的控制。

企業A有如下要求:

  • 直傳資料:企業A不希望所有App都通過企業的服務端應用伺服器(Application Server)來進行資料中轉,而希望能夠直連OSS上傳或下載資料。

  • 安全管控:企業A不希望將存取金鑰(AccessKey)儲存到行動裝置中,因為行動裝置是歸屬於使用者控制,屬於不可信的運行環境。

  • 風險控制:企業A希望將風險控制到最小,每個App直連OSS時都必須擁有最小的存取權限且訪問時效需要很短。

解決方案

當行動裝置 App(App)直連OSS上傳或下載資料時,App需要嚮應用伺服器申請訪問憑證。應用伺服器以RAM使用者身份扮演RAM角色,調用STS API AssumeRole介面擷取臨時安全性權杖,並將臨時安全性權杖傳遞給App,App使用臨時安全性權杖訪問OSS。

行動裝置應用訪問阿里雲

  1. App嚮應用伺服器申請訪問憑證。

  2. 使用阿里雲帳號A建立一個RAM角色,並為RAM角色授予合適的許可權。

    具體操作,請參見建立RAM角色並授權

  3. 使用阿里雲帳號A為應用伺服器建立一個RAM使用者,並允許應用伺服器以RAM使用者身份扮演該RAM角色。

    具體操作,請參見建立RAM使用者並允許扮演RAM角色

  4. 應用伺服器通過調用STS的AssumeRole介面擷取RAM角色的臨時安全性權杖。

  5. 應用伺服器可以進一步限制臨時安全性權杖的許可權,以更精細地控制每個App的許可權。

    具體操作,請參見限制臨時安全性權杖的許可權

  6. 當App需要直連OSS上傳或下載資料時,可以使用臨時安全性權杖訪問OSS進行資料直傳。

建立RAM角色並授權

假設阿里雲帳號A的帳號ID為123456789012****

  1. 使用阿里雲帳號A建立可信實體為雲帳號的RAM角色oss-objectmanager

    說明

    建立RAM角色時選擇當前雲帳號作為信任主體,即只允許阿里雲帳號A下的RAM使用者來扮演該RAM角色。

    具體操作,請參見建立可信實體為阿里雲帳號的RAM角色

    RAM角色建立成功後,在角色基本資料頁面可以查看到該RAM角色的ARN和信任策略。

    • RAM角色的ARN為acs:ram::123456789012****:role/oss-objectmanager

    • RAM角色的信任策略如下。

      說明

      以下策略表示只允許阿里雲帳號A下的RAM使用者來扮演RAM角色。

      {
        "Statement": [
          {
            "Action": "sts:AssumeRole",
            "Effect": "Allow",
            "Principal": {
              "RAM": [
                "acs:ram::123456789012****:root"
              ]
            }
          }
        ],
        "Version": "1"
      }
  2. 為RAM角色授權。為RAM角色oss-objectmanager授予OSS的系統管理權限AliyunOSSFullAccess

    具體操作,請參見為RAM角色授權

建立RAM使用者並允許扮演RAM角色

  1. 使用阿里雲帳號A為應用伺服器建立RAM使用者appserver

    具體操作,請參見建立RAM使用者

  2. 為建立好的RAM使用者授予AliyunSTSAssumeRoleAccess許可權,即允許RAM使用者扮演RAM角色。

    具體操作,請參見為RAM使用者授權

應用伺服器擷取臨時安全性權杖

  1. 應用伺服器使用RAM使用者的存取金鑰(AccessKey)調用STS的 AssumeRole介面。

    說明
    • 使用阿里雲CLI前需要在應用伺服器中安裝CLI工具,並使用RAM使用者的AccessKey配置相應憑證。具體操作,請參見STS CLI參考

    • 當前CLI樣本中未指定Policy參數,因此返回的臨時安全性權杖將擁有RAM角色oss-objectmanager的所有許可權。您也可以額外限制臨時安全性權杖的許可權,更多資訊,請參見限制臨時安全性權杖的許可權

    使用阿里雲CLI調用AssumeRole的樣本如下:

    aliyun sts AssumeRole --RoleArn 'acs:ram::123456789012****:role/oss-objectmanager' --RoleSessionName 'client-001'
  2. STS服務將臨時安全性權杖返回給應用伺服器。返回的臨時安全性權杖中包含AccessKeyIdAccessKeySecretSecurityToken

    返回樣本如下:

    {
         "AssumedRoleUser": {
             "AssumedRoleId": "391578752573****:client-001",
             "Arn": "acs:ram::123456789012****:role/oss-objectmanager/client-001"
         }, 
         "Credentials": {
             "AccessKeySecret": "yourAccessKeySecret",
             "SecurityToken": "yourSecurityToken",
             "Expiration": "2016-01-13T15:02:37Z",
             "AccessKeyId": "yourAccessKeyId"
         }, 
         "RequestId": "E1779AAB-E7AF-47D6-A9A4-53128708B6CE"
     }
    說明

    SecurityToken到期時間較短。如果需要一個較長的到期時間,應用伺服器需要重新頒發臨時安全性權杖,例如:每隔1800秒頒發一次。

限制臨時安全性權杖的許可權

您可以使用Policy參數來根據使用者或裝置限制不同臨時安全性權杖的許可權,避免越權風險。

以下樣本表示:只允許下載sample-bucket/2015/01/01/*.jpg

  • 請求樣本

    aliyun sts AssumeRole --RoleArn 'acs:ram::123456789012****:role/oss-objectmanager' --RoleSessionName 'client-002' --Policy '{"Version":"1", "Statement": [{"Effect":"Allow", "Action":"oss:GetObject", "Resource":"acs:oss:*:*:sample-bucket/2015/01/01/*.jpg"}]}'
    說明

    臨時安全性權杖到期時間預設值為3600秒,通過DurationSeconds參數可以設定到期時間。更多資訊,請參見AssumeRole - 擷取扮演角色的臨時身份憑證

  • 返回樣本

    {
       "AssumedRoleUser": {
           "AssumedRoleId": "391578752573****:client-002",
           "Arn": "acs:ram::123456789012****:role/oss-objectmanager/client-002"
       },
       "Credentials": {
           "AccessKeySecret": "yourAccessKeySecret",
           "SecurityToken": "yourSecurityToken",
           "Expiration": "2016-01-13T15:03:39Z",
           "AccessKeyId": "yourAccessKeyId"
       }, 
       "RequestId": "98835D9B-86E5-4BB5-A6DF-9D3156ABA567"
    }

App使用臨時安全性權杖訪問OSS

  1. 應用伺服器將臨時安全性權杖傳遞給App。

  2. App使用臨時安全性權杖訪問OSS。

    本樣本為您示範如何在Android應用中整合阿里雲OSS Android SDK,並通過臨時安全性權杖訪問OSS,實現將遠程檔案下載至本地裝置的功能。範例程式碼如下:

    // yourEndpoint填寫Bucket所在地區對應的Endpoint。以華東1(杭州)為例,Endpoint填寫為https://oss-cn-hangzhou.aliyuncs.com。
    String endpoint = "yourEndpoint";
    // yourRegion填寫Bucket所在地區。以華東1(杭州)為例,region填寫為cn-hangzhou。
    String region = "yourRegion";
    
    // 從STS服務擷取的臨時存取金鑰(AccessKeyID和AccessKeySecret)。
    String accessKeyId = "yourAccessKeyId";
    String accessKeySecret = "yourAccessKeySecret";
    // 從STS服務擷取的臨時安全性權杖(SecurityToken)。
    String securityToken = "yourSecurityToken";
    
    OSSCredentialProvider credentialProvider = new OSSStsTokenCredentialProvider(accessKeyId, accessKeySecret, securityToken);
    ClientConfiguration config = new ClientConfiguration();
    config.setSignVersion(SignVersion.V4);
    // 建立OSSClient執行個體。
    OSSClient oss = new OSSClient(getApplicationContext(), endpoint, credentialProvider);
    oss.setRegion(region);
    // 構造下載檔案請求。
    GetObjectRequest get = new GetObjectRequest("sample-bucket", "2015/01/01/grass.jpg");
    
    OSSAsyncTask task = oss.asyncGetObject(get, new OSSCompletedCallback<GetObjectRequest, GetObjectResult>() {
        @Override
        public void onSuccess(GetObjectRequest request, GetObjectResult result) {
            // 請求成功。
            Log.d("asyncGetObject", "DownloadSuccess");
            Log.d("Content-Length", "" + result.getContentLength());
            
            try (InputStream inputStream = result.getObjectContent()) {
                byte[] buffer = new byte[2048];
                int len;
                while ((len = inputStream.read(buffer)) != -1) {
                // 處理資料
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        @Override
        // GetObject請求成功,返回GetObjectResult。GetObjectResult包含一個輸入資料流的執行個體。您需要自行處理返回的輸入資料流。
        public void onFailure(GetObjectRequest request, ClientException clientExcepion, ServiceException serviceException) {
            // 請求異常。
            if (clientExcepion != null) {
                // 本地異常,如網路異常等。
                clientExcepion.printStackTrace();
            }
            if (serviceException != null) {
                // 服務異常。
                Log.e("ErrorCode", serviceException.getErrorCode());
                Log.e("RequestId", serviceException.getRequestId());
                Log.e("HostId", serviceException.getHostId());
                Log.e("RawMessage", serviceException.getRawMessage());
            }
        }
    });
    // 取消任務。
    // task.cancel(); 
    // 等待任務完成。
    // task.waitUntilFinished();