全部產品
Search
文件中心

Simple Log Service:採集-搭建移動端日誌直傳服務

更新時間:Aug 07, 2024

在移動互聯時代,直接通過手機應用上傳資料變得越來越普遍。針對日誌情境,您也可以將移動端應用的日誌直接上傳到Log Service。本文介紹如何搭建移動端應用日誌的直傳服務。

背景資訊

  • 普通模式下,寫日誌到Log Service需要開啟阿里雲帳號的存取金鑰AK,用於鑒權及防篡改。如果通過此模式上傳日誌到Log Service,需要將您阿里雲帳號的AK儲存在移動端應用中,會存在AK泄漏風險。如果發生AK泄漏,則會威脅該帳號下雲資源的安全。

  • 另一種方式是通過應用伺服器中轉,但是使用該模式,您的應用伺服器需要承載所有的移動端資料,對應用伺服器的壓力較大。

  • 為了避免以上問題,阿里雲提供更安全、便捷的移動端應用日誌採集方案。RAM角色通過STS擷取可以自訂時效和存取權限的臨時身份憑證。使用該臨時令牌,可搭建直傳服務實現行動裝置將應用日誌直接上傳到日誌庫。

方案概覽

  1. 移動端應用嚮應用伺服器發起請求,申請擷取臨時安全性權杖;

  2. 應用伺服器檢測移動端請求的合法性(可以結合業務的實際情況如:登入態、對稱式加密等),若通過校正,應用伺服器需要使用提前建立的RAM使用者產生的AK作為訪問憑據,向STS服務發起AssumeRole介面調用,申請RAM使用者扮演目標RAM角色;

  3. STS服務檢測AK合法性,並驗證RAM使用者是否具備扮演目標RAM角色的許可權,若通過校正,STS服務返回臨時安全性權杖給應用伺服器;

  4. 應用伺服器擷取臨時安全性權杖後,返回臨時安全性權杖給移動端應用;

  5. 移動端應用擷取臨時安全性權杖後,使用臨時安全性權杖訪問Log Service;

  6. Log Service通過RAM/STS服務驗證臨時安全性權杖合法性,並驗證RAM角色是否具備訪問目標日誌庫的許可權,若通過校正,Log Service處理移動端應用的上傳日誌請求,並返回上傳結果給移動端應用。

名詞解釋

節點

說明

Android/iOS應用

終端使用者的移動端應用,日誌的來源。

SLS

阿里雲Log Service,負責儲存應用上傳的日誌。

RAM/STS

阿里雲存取控制,提供使用者身份管理和資源存取控制服務,負責產生臨時安全憑證(STS Token)。

應用伺服器

提供從STS擷取臨時訪問憑證的服務以及使用者在應用中上傳資料的中繼資料資訊。

步驟一:在Log Service中建立Project和Logstore

  1. 登入Log Service控制台

  2. 建立專案Project,輸入樣本Project名稱:slstestproject。

  3. 建立Logstore,輸入樣本Logstore名稱:slstestlogstore。

步驟二:建立RAM使用者並完成角色扮演授權

  1. RAM使用者的建立詳細步驟請參考:建立RAM使用者。本樣本使用的RAM使用者為:ramslsuser。下面步驟中會使用系統會自動產生存取金鑰AccessKey,請記錄並妥善儲存AccessKey。

  2. 授予RAM使用者調用STS服務AssumeRole介面的許可權:

    a. 在使用者頁面,單擊目標RAM使用者操作列的添加許可權。

    b. 在新增授權頁面,選中系統策略下的AliyunSTSAssumeRoleAccess,然後單擊確認新增授權image

步驟三:建立RAM角色並完成資源授權

  1. 建立RAM角色的詳細步驟請參考:建立可信實體為阿里雲帳號的RAM角色,樣本值如下所示:

    參數

    說明

    角色名稱

    輸入角色名稱,例如ramslsrole

    備忘

    輸入備忘資訊

    選擇信任的雲帳號

    選擇當前雲帳號(UID)

  2. 建立完成後,在角色頁面,找到ramslsrole角色,單擊角色名稱,查看並記錄角色ARN。image

  3. 通過指令碼編輯模式建立自訂策略。更多資訊請參考:建立自訂權限原則,樣本值如下所示:

    參數

    說明

    名稱

    輸入自訂策略名稱稱,例如putlogspolicy

    備忘

    輸入備忘資訊

    策略內容

    {
      "Version": "1",
      "Statement": [
        {
          "Action": [
            "log:PostLogStoreLogs",
            "log:PutLogs"
          ],
          "Resource": "acs:log:*:*:project/slstestproject/*",
          "Effect": "Allow"
        }
      ]
    }
  4. 為RAM角色授予自訂權限原則,在角色頁面,找到RAM角色ramslsrole,單擊RAM角色操作列的添加許可權

    image

步驟四:搭建應用伺服器

本教程提供了多個語言的版本樣本程式供您下載,下載地址請參見PHP、Java、Ruby、Node.js

  1. 設定檔

    樣本中,每個語言套件內均有一個管理配置的config.json檔案,可對配置進行修改。

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

    參數

    說明

    AccessKeyID

    RAM使用者的存取金鑰ID。

    AccessKeySecret

    RAM使用者的存取金鑰Secret。

    RoleArn

    RAM角色的RoleArn。

    TokenExpireTime

    移動端應用擷取到的Token的失效時間。

    最少是900s,可以不修改預設值。

    PolicyFile

    Token所要擁有的許可權列表的檔案,可以不修改預設值。

    此處提供兩種最常用Token許可權檔案,位於policy目錄下面。 您也可以根據業務需求設計policy檔案。

    • write_policy.txt:指定了該Token擁有該帳號下Project的寫入許可權。使用write_policy.txt許可權檔案時,請根據實際替換該檔案中的Project名稱。

    • readonly_policy.txt:指定了該Token擁有該帳號下Project的讀取許可權。

    Token的最終許可權為RAM角色許可權與許可權檔案的許可權交集。如果未設定許可權檔案,則Token的最終許可權為RAM角色許可權。

  2. 運行範例程式碼

    程式碼範例的運行方法:對於Java版本(依賴於Java 1.7+),將包下載解壓後,建立一個Java工程,將依賴和代碼以及配置拷貝到Java工程中,運行main函數即可,程式預設會監聽7080連接埠,等待HTTP請求,其他語言類似。

步驟五:移動端直傳

  1. 擷取安全性權杖STS Token:

    以HTTP請求形式訪問服務的7080連接埠,擷取臨時安全性權杖。返回結果樣本如下:

    {
      "StatusCode":"200",
      "AccessKeyId":"STS.3pdgagd****",
      "AccessKeySecret":"rpnwO9wr34tGdrddgsR2Y****",
      "SecurityToken":"CAES+wMIARKAAZhjH0EUOIhJMQBMjR****tZGVtbzI=",
      "Expiration":"2021-11-20T08:23:15Z"
    }                          
  2. 移動端直傳:

    範例程式碼示範通過移動用戶端使用臨時安全性權杖直接將日誌寫入到日誌庫中。

    const ALY = require("aliyun-sdk");
    
    const sls = new ALY.SLS({
      accessKeyId: "Your temporary accesKeyId",
      secretAccessKey: "Your temporary accessKeySecret",
      securityToken: "Your sts token",
      endpoint: "http://cn-hangzhou.log.aliyuncs.com",
    });
    
    // -------------------------------
    // put logs
    // -------------------------------
    const projectName = "your_project_name";
    const logStoreName = "your_logstore";
    
    const logGroup = {
      logs: [
        {
          time: Math.floor(new Date().getTime() / 1000),
          contents: [
            {
              key: "a",
              value: "1",
            },
            {
              key: "a",
              value: "2",
            },
            {
              key: "a",
              value: "3",
            },
          ],
        },
      ],
      topic: "vv",
      source: "127.0.0.1",
    };
    
    sls.putLogs(
      {
        //必選欄位
        projectName: projectName,
        logStoreName: logStoreName,
        logGroup: logGroup,
      },
      function (err, data) {
        if (err) {
          console.log("error:", err);
          return;
        }
    
        console.log("success:", data);
      }
    );