在移动互联时代,直接通过手机应用上传数据越来越普遍。针对日志场景,您也可以将移动端应用的日志直接上传到日志服务,不需要通过应用服务端中转。本文介绍如何搭建移动端应用日志直传服务。

背景信息

普通模式下,写日志到日志服务需要开启阿里云账号的访问密钥(AccessKey),用于鉴权及防篡改。如果通过此模式上传日志到日志服务,需要将您阿里云账号的AccessKey保存在移动端应用中,会存在AccessKey泄漏风险。一旦发生AccessKey泄漏,需要升级移动端应用,并替换AccessKey,代价太大。另一种模式是通过应用服务器中转,但是使用该模式,如果移动端应用数量较大,您的应用服务器需要承载所有的移动端数据,对服务器的规模有较高的要求。

为了避免以上问题,日志服务提供更安全、便捷的移动端应用日志采集方案,即通过阿里云RAM搭建一个基于移动服务的移动端应用日志直传服务。所谓直传就是移动端应用通过直连方式访问日志服务,只有控制流需要通过您的应用服务器。您可以创建日志服务的RAM角色,并配置移动端应用作为RAM用户扮演该角色,从而实现在30分钟内搭建一个移动端应用日志直传服务。

优势

通过RAM服务搭建一个移动端应用日志直传服务,具有以下优势:
  • 访问方式更加安全。临时、灵活的赋权鉴权。
  • 成本低。您无需准备大量服务器。
  • 高并发,支持海量用户。日志服务支持海量的上传和下载带宽。
  • 弹性。日志服务具有无限扩容的存储空间。

服务架构

架构图如下所示。架构图
架构说明如下表所示。
节点 说明
Android/iOS应用 最终用户的移动端应用,日志的来源。
SLS 阿里云日志服务,负责存储应用上传的日志。
RAM/STS 阿里云访问控制,提供用户身份管理和资源访问控制服务,负责生成临时上传凭证。
应用服务器 提供移动端应用的开发者开发的移动端应用后台服务,管理应用上传和下载的Token,以及用户在应用中上传数据的元数据信息。

配置流程

  1. 移动端应用向您的应用服务器申请一个临时上传凭证(下文将此临时上传凭证称为Token)。

    不能在移动端应用中直接存储AccessKey,这样会存在泄密风险。所以移动端应用必须向您的应用服务器申请一个Token,该Token具备时效性。如果Token的过期时间为30分钟(这个时间可以通过应用服务器指定),那么在这30分钟内,对应的移动端应用可以使用该Token访问日志服务, 30分钟后再重新获取。

  2. 您的应用服务器检测上述请求的合法性,然后返回Token给移动端应用。
  3. 移动端应用获取Token后,可访问日志服务。

本文主要介绍应用服务器如何向RAM服务申请Token和移动端应用如何获取Token。

操作步骤

  1. 授权RAM角色操作日志服务。

    创建日志服务的RAM角色,并配置移动端应用作为RAM用户扮演该角色,详细步骤请参见创建可信实体为阿里云账号的RAM角色及授权

    配置完成后,您将获取以下信息。
    • RAM用户的AccessKey ID、AccessKey Secret。
    • RAM角色的标识RoleArn。
  2. 搭建一个应用服务器。

    为了方便开发,本教程提供了多个语言的版本示例程序供您下载,下载地址请参见PHP、Java、Ruby、Node.js

    每个语言包下载下来后,都会有一个配置文件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的写入权限。
    • readonly_policy.txt:指定了该Token拥有该账号下Project的读取权限。

    代码示例的运行方法:对于Java版本(依赖于Java 1.7+),将包下载解压后,新建一个Java工程,将依赖和代码以及配置拷贝到工程里面,运行main函数即可,程序默认会监听7080端口,等待HTTP请求,其他语言类似。

    返回的数据格式
    //正确返回
    {
        "StatusCode":200,
        "AccessKeyId":"STS.3pdgagd****",
        "AccessKeySecret":"rpnwO9wr34tGdrddgsR2Y****",
       "SecurityToken":"CAES+wMIARKAAZhjH0EUOIhJMQBMjR****tZGVtbzI=",
       "Expiration":"2021-11-12T07:49:09Z",
    }
    
    //错误返回
    {
        "StatusCode":500,
        "ErrorCode":"InvalidAccessKeyId.NotFound",
        "ErrorMessage":"Specified access key is not found."
    }
    
                                
    • 正确返回说明(下面五个变量将构成一个Token)
      状态码 说明
      StatusCode 获取Token的状态。获取成功时,返回值是200。
      AccessKeyId 移动端应用初始化LogClient获取的AccessKey ID。
      AccessKeySecret 移动端应用初始化LogClient获取的AccessKey Secret。
      SecurityToken 移动端应用初始化的Token。
      Expiration Token失效的时间。

      Android SDK会自动判断是否失效,自动获取Token。

    • 错误返回说明
      错误码 说明
      StatusCode 获取Token的状态。获取失败时,返回值是500。
      ErrorCode 错误码。
      ErrorMessage 错误的具体信息。
  3. 移动端构造HTTP请求,从应用服务器获取Token。
    HTTP请求及回应格式如下。
    Request URL: GET https://localhost:7080/
    
    Response:
    {
    "StatusCode":"200",
    "AccessKeyId":"STS.3pdgagd****",
    "AccessKeySecret":"",
    "SecurityToken":"",
    "Expiration":"2021-11-20T08:23:15Z"
    }
                                
    说明 本文档中所有示例仅为演示服务器搭建流程,您可以在此基础上进行自定义开发。