1. 地球号对象服务

地球号对象服务封装了JSON对象服务,FOBJ对象服务和AVATAR头像服务。

2. 涉及的表格

表格 表名 说明
obj 对象表 存储所有对象
objc 对象目录表 存储对象的目录,开发者可以创建目录
objr 目录权限表 obj rule,把objc分配给不同app的权限表,表里有oss管理文件的policy
obja 对象访问表 存储可以操作的对象许可码。每个许可码规定一个app可以怎么操作(action)一个objc
objl 对象访问表 存储最近的对象操作日志
obje 访问异常表 存储最近的对象操作异常日志,只有error,debug,event三项,用于尽可能的保存异常
osts OSS操作临时授权表 主要获取文件上传的sts和obja

3. 数据库流程图

对象服务表格集合
Figure: 对象服务表格集合

3.1. addObj接口的原理流程图

对象服务表格集合
Figure: 对象服务表格集合
  • 接口请求objr_id,okey,obj_data

    [!note|label:为什么不用objc_id?] 有些objc是公共目录,访问它的权限只能由神店管理员配置,也就是说,只有神店的God才可以配置哪哪个app_id能访问这些公共目录。所以,这些objr的id不是谁都能看见的,就是不希望这些公共目录都给是可以用这个信息公开化,而是每个人只能看到自己的objr_id

  • 验证objr[objr_id]对应state,stato,expire是否有效?

  • 添加到obj表,objl表,如果异常加入obje表。


3.2. addFobj接口的原理流程图

文件对象流程
Figure: 文件对象流程

首先,对象服务包含JSON对象和FILE对象。这是两套接口,再加上obj通用这套接口,一共一套接口。但创建对象的即包含addFobj,addJobj

fobj: 文件对象,它的创建和删除,修改,都是函数计算触发的。所以不占接口列表。 jobj: json对象,它的创建,删除,修改,都占接口列表。

这里面有个非常重要的讨论就是: jobj的创建和计数都是可控的,控制在每个app,shop,token_user_id,token_own_id,token_id这个级别。

但fobj就不行了,包含:

  1. 拥有OSS权限的人可以直接用OSS工具上传。
  2. 如果A用户知道了B用户的channel,也可以把文件传入进去,触发B用户文件记录和计费。可以恶意攻击B用户的商业行为。

我们的做法,在OSS上创建足够多的RAM用户,赋予不同的用户不同的权限。

[对象存储 OSS > 产品简介 > 功能概览]https://help.aliyun.com/document_detail/52830.html?spm=5176.8465980.entries.6.3c991450fq9jb7

我们尤其注意OSS权限的做法

ACL:OSS 为权限控制提供访问控制列表(ACL)。ACL是授予存储空间和对象访问权限的访问策略。 您可以在创建存储空间或上传对象时配置ACL,也可以在创建存储空间或上传对象后的任意时间内修改ACL。

[!note|label:ACL能做什么?] ACL的处理粒度,要么是对整个Bucket,要么是对某个具体的文件。 Bucket Policy:您可以通过控制台的Bucket Policy功能方便直观地授权其他用户访问您的OSS资源, 例如向其他账号的RAM用户授予访问权限,以及向匿名用户授予带特定IP条件限制的访问权限。 [!note|label:Bucket方式能做什么?] ACL的处理粒度,要么是对整个Bucket,要么是对某个具体的文件。 [!note|label:RAM能做什么?] RAM Policy:您可以构建RAM Policy来控制存储空间和文件夹的访问权限。OSS提供了RAM策略编辑器帮助您快速生成RAM Policy。RAM Policy Editor

既然阿里云建议用BucketPolicy,我们就用BucektPolicy

针对存放在 Bucket 的 Object 的访问,OSS 提供了多种权限控制方式,包括 ACL、Bucket Policy 和 RAM Policy。 ACL:OSS 为权限控制提供访问控制列表(ACL)。ACL是基于资源的授权策略,可授予 Bucket 和 Object 访问权限。 您可以在创建 Bucket 或上传 Object 时设置 ACL,也可以在创建 Bucket 或上传Object 后的任意时间内修改 ACL。 RAM Policy:RAM (Resource Access Management)是阿里云提供的资源访问控制服务。RAM Policy 是基于用户的授权策略。通过设置 RAM Policy,您可以集中管理您的用户(比如员工、系统或应用程序),以及控制用户可以访问您名下哪些资源的权限。 比如能够限制您的用户只拥有对某一个 Bucket 的读权限。子账号是从属于主账号的,并且这些账号下不能拥有实际的任何资源,所有资源都属于主账号。RAM Policy 操作比较复杂,强烈推荐您使用 Bucket Policy。 Bucket Policy:Bucket Policy 是基于资源的授权策略。相比于 RAM Policy,Bucket Policy 操作简单,支持在控制台直接进行图形化配置,并且 Bucket 拥有者直接可以进行访问授权,无需具备RAM 操作权限。Bucket Policy 支持向其他账号的 RAM 用户授予访问权限,以及向匿名用户授予带特定IP条件限制的访问权限。

4. 所以要参考的文件是

使用Bucket Policy授权其他用户访问OSS资源

BucketPolicy BucketPolicy

选择子账号:您可以从下拉菜单中选择当前账号的子账号,授予资源访问权限。若账号较多时,您也可以直接在搜索框输入子账号名称,搜索支持模糊匹配。您的账号必须是主账号,或拥有此Bucket管理权限及RAM控制台ListUsers权限的子账号,否则无法查看当前账号的子账号列表。 其他账号:您可以给其他主账号、子账号以及通过STS生成的临时用户授予访问权限。 当您需要给其他主账号或子账号授权时,请输入被授权账号的UID。 当您需要给临时用户授权时,输入格式为arn:sts::{RoleOwnerUid}:assumed-role/{RoleName}/{RoleSessionName}。例如生成临时用户时使用的角色为testrole,角色拥有者的主账号UID为12345,生成临时用户时指定的RoleSessionName为testsession。此时应填写arn:sts::12345:assumed-role/testrole/testsession。生成临时授权用户的操作请参见STS临时授权访问OSS。 匿名账号():若您需要给所有用户授权,可以选择匿名账号()。

[!note|label:注意]

  • 当被授权的用户是其他阿里云主账号时,该账号无法通过OSS控制台访问授权资源,您可以通过命令行工具ossutil、图形化工具ossbrowser、OSS SDK、OSS API访问授权资源。
  • 当被授权的用户是STS临时用户时,该账号无法通过OSS控制台访问授权资源,您可以通过命令行工具ossutil、OSS SDK、OSS API访问授权资源。 给RAM用户授予ListUsers权限请参见为RAM用户授权。

注意,一个子用户可以赋予多个channel的权限,而我们要做的是把一个子账户和多个channel在数据库关联起来。

我们要做的是,

  1. 管理员用户可以通过ossutil和windows的ossclient上传文件。整个好说,是我们自己内部人做的。
  2. 开发人员可以通过临时申请STS临时授权。这个不好弄。 如何让不同的用户

我们以前的做法是在让STS服务具备osser的角色(这个角色可以访问所有OSS资源)函数计算直接从context上下文获取角色的子账户的accesskeyid和accessKeySecret,这样很危险,是把子账户的返回了。

# -*-# -*- coding: utf-8 -*-

def handler(event, context):
  response = {
     'isBase64Encoded': False,
       'statusCode': 200,
       'headers': None,
      'body': {
        "access_key_id":context.credentials.access_key_id ,
        "access_key_secret": context.credentials.access_key_secret,
        "security_token" : context.credentials.security_token
      }
  }
p
  return response

我们的做法,规定bucket的子文件夹为最小控制粒度。但avatar.xdua.com是个特例。我们很希望有avatar.xdua.com/12345678.jpg 这样的短码路径。这样对user表压力也小。另外avatar仅仅是头像,它有自己独立的应用特征

1:文件都很小 2:只接受putObject接口,不支持断点续传,和multipart上传。 3:正因为只有putObject接口,我们就可以轻松的从obj的etag上获取它的MD5,然后转成8位短码。 4:头像上传还需要返回头像地址,因为网页上要立刻刷新显示。 5: 头像存储的OSS对象名不能有路径,这个必须SDK来控制。

avatar与普通的obj还不一样,

5. 如何搞定头像上传

【本方案已废弃】

第一步:创建一个专门上传头像的子账户,因为头像服务是全局服务,整个地球号就只需要一个。同时也创建全控账户,全空账户主要用来在控制台调用delObj来删除不用的obj的

创建头像上传账号 创建头像全控账号

第二步:

函数计算增加OSS触发
Figure: 函数计算增加OSS触发

这个账号是可读/可写,那为什么不选择完全控制呢,因为完全控制,意味着可以删除,但我们不需要删除。

第三步:php集成OTS

https://github.com/ShaoZeMing/Aliyun-Sts

第四步:浏览器端上传obj的时候必须有对应的meta,否则传入就失败。

浏览器如何创建带meta-tag的SDK
Figure: 浏览器如何创建带meta-tag的SDK

第五步:在后台读取上传的文件里相关的meta从oss.obj读出来存入数据库。

PHP读出来meta-tag
Figure: PHP读出来meta-tag

6. 地球号对象的skema

地球号的skema包含如下

skema 解释
int 一个整形数据
string 一个字符串
fobj 一个文件对象{"etag": "FC3FF98E8C6A0D3087D515C0473F8677", "owner": "35006007"} okey就是文件的路径,加上前缀 http://file.xdua.com/就促成了文件对象的全路径

7. 如何解决OSS死循环?

  • 在阿里云控制台删除某个文件对象,引发BUcket里的真实文件被删除,删除的结果是,引发dua_trg_fobj函数计算。这并不是一个死循环,而是一个多余迭代。 解决方法:dua_trg_foby不要对文件删除敏感触发,删除操作只能在地球号控制台进行。

  • 在地球号控制台硬删bucket里的某个文件,导致dua_trg_fobj被触发。 解决方法:dua_trg_foby不要对文件删除敏感触发,删除操作只能在地球号控制台进行。

怎么免疫文件删除,在dua_trg_fobj的对象触发器那里,不要加DeleteObj的相关触发。

8. 为什么要在文件上传的时候设计meta-objr-id标签?

obj的每个objcato都是用户自己创建的,但我们也有公用的cato。功能要支持如下功能

  • 公共的objc,大家都可以访问。尤其是神店创建的那么多官方objc,要有一个方法可以管理这个可以这个访问,哪个可以访问。

  • 有些开发者创建的Objc,这个是zone的属性。开发者可以配置,自己的Objc可以让哪个zone的user_id通过哪个app来访问。这种控制其实是控制了osssts的发放。

现在就是objr这个标签命名太难听了。

8.1. 问题,如果程序员通过别的channel申请获取一个ststoken,然后上传的时候通过token检查。上传到channl2里,完美绕过上传验证,如何应对?

一个方法是,可以把得到的授权做成token,但开发者仍旧可以用这个机制来绕过去。从公共的频道获取token,用到本次上传。

9. 如何设计文件上传机制?

第一步:确定objc_id(这个可以在公告文档中,也可以在开发者提供的目录)

地球号提供几个公共的cato,这个是地球号提供的免费公共服务。比方说
`TempCato`这个cato,你可以上传文件到这个cato,但文件保留24小时候就会被自动删除。

第二步:通过sts接口,获取一个临时文件上传sts.key/secret,并且有一个token用于放到meta里

这个地方要向接口提供 objc_id,而发起者自己的authorization会告诉sts接口自己的shop,app_id,user_id. sts接口还会返回一个objacs_id,这个objacs_id是个临时创建的表项。是个8位短码。 obja表存了对象名,channel,要传的文件名。

第三步:客户端上传文件时把obja_id放到meta里,

第四步: OSS触发函数dua_trg_fobj会检查obja_id,

通过obja_id搜查obja表,获取objc_id,okey,app 比较obja_表预定的okey和oss_event里的objk是否一致?

如果object_key一致,就可以把这个对象写入表了。

如果检查失败,就会标记例外到obje表里
如果检查成功,就会记录到obj表

10. 文件fobj_jkey命名规范,必须是一个8位的cato号和后续的oejbect_key。

现在的问题是,如果强硬把objc_id植入到objk的命名里。会出现这样的问题

+ 开发者A创建了一个`ExampleC`的objc。
+ 开发者A把它广告给其它所有人。
+ 用户开始把文件传到这个目录
+ 文件越来越多
+ 开发者A注销了`ExampleC`这个objc。
+ 这个目录下的文件都失效了。
+ 开发者A删除了`ExampleC`这个objc,也相当于删除了这个目录。
+ 这个目录下的所有文件都消失了。
+ 这些文件不可以重用了

这个问题很严重,我们需要再三考虑。

考虑的结果是:objc_id一旦创建,就不能改变。obj_key中一定要有个8位的objc_id。这样创建的文件obj一旦创建,就不能改变了。

results matching ""

    No results matching ""