使用S3协议访问OSS

  • 一、前提
  • 0、OSS对S3的兼容性
  • 1、权限控制:
  • 1. RAM policy
  • 2. bucket policy
  • 3. bucket ACL
  • 4. object ACL
  • 2、同地域的ECS访问OSS 可以使用内网访问,不走流量。
  • 3、bucket删除:
  • 需要先关闭关联日志(如果有):
  • 删除:
  • 二、创建bucket
  • 1、创建bucket
  • 2、S3协议访问,需要暴露headers ETag
  • 3、权限控制使用Bucket授权策略
  • 4、控制台上传文件
  • 三、使用S3协议Go SDK访问OSS
  • 1、配置
  • 2、简单访问


一、前提

0、OSS对S3的兼容性

OSS对S3兼容文档地址:https://help.aliyun.com/document_detail/389025.html

1、权限控制:

文档地址:https://help.aliyun.com/document_detail/430201.html

针对存放在Bucket的Object的访问,OSS提供了以下权限控制策略:

1. RAM policy

基于用户的授权策略。
适用场景:

  • 同一个账户下的不同RAM用户授予相同权限。
  • OSS服务级别权限配置。
  • 对多个bucket设置相同权限。
  • 临时账号访问权限控制。

2. bucket policy

  • 可以指定用户授予权限
  • 可以授予匿名用户限制IP的访问权限

使用场景:

  • 对同一账号下的不同RAM用户授予不同权限。
  • 要进行跨账号或对匿名用户授权。

3. bucket ACL

(一般默认私有,不做改动)
Bucket ACL分为public-read-write(公共读写)、public-read(公共读)和private(私有)三种。
使用场景:

  • 对单个Bucket内的所有Object设置相同的访问权限。

4. object ACL

(一般继承bucket ACL,不做改动)
Object ACL分为继承Bucket、public-read-write(公共读写)、public-read(公共读)和private(私有)四种。
使用场景:

  • 对单个Object单独授权。

例如,已通过RAM Policy或者Bucket Policy将Bucket内的所有Object或者与指定Prefix匹配的Object的访问权限设置为私有,但是考虑到您需要将其中某个Object开放给所有互联网匿名用户访问,则选择Object ACL,并将ACL设置为public-read。

当前测试使用基于bucket policy对指定用户进行授权。

2、同地域的ECS访问OSS 可以使用内网访问,不走流量。

我的云服务器ECS:华北2:北京
我的OSS资源包:大陆通用,新建一个bucket同属华北2:北京地域即可。

3、bucket删除:

对象存储-bucket列表-bucketname下

需要先关闭关联日志(如果有):

  • 日志管理-实时查询-右侧关闭关联日志

删除:

  • 基础设置-最下面删除

二、创建bucket

1、创建bucket

  • 地域选择华北2-北京
  • 开启实施日志查询

iOS s3协议 标准s3协议_网络


iOS s3协议 标准s3协议_html_02

2、S3协议访问,需要暴露headers ETag

权限管理-跨域设置-创建规则

  • 方便测试,允许methods全选,来源和允许headers用 *

iOS s3协议 标准s3协议_网络_03

3、权限控制使用Bucket授权策略

在此之前先创建一个 RAM 子账号:
权限管理-访问控制RAM:前往控制台:
RAM访问控制-身份管理-用户-创建用户:

  • 访问方式:选中Open API调用访问即可。无需添加任何权限。
  • 【重要】记住 AccessKey ID和AccessKey Secret,记不住再创建新的也可以。

权限管理-Bucket授权策略-按图形策略添加:

  • 新增授权
  • 授权资源:整个bucket
  • 授权用户:选中子账户,选择刚才创建的RAM子账户
  • 授权操作:简单设置-完全控制(测试使用完全控制即可)

4、控制台上传文件

文件管理-上传文件-扫描文件-选择本地的1.jpg-上传文件。
查看文件管理,文件上传成功。

三、使用S3协议Go SDK访问OSS

1、配置

历史原因,aws sdk for go使用的V1版本,现在有V2版本可用。
文档地址:https://docs.aws.amazon.com/zh_cn/sdk-for-go/?id=docs_gateway
github地址:https://github.com/aws/aws-sdk-go
oss文档地址:https://help.aliyun.com/product/31815.html

公共云下OSS Region和Endpoint对照表
文档地址:https://help.aliyun.com/document_detail/31837.html
我们这里是华北2-北京:

Region :oss-cn-beijing
外网Endpoint:oss-cn-beijing.aliyuncs.com
内网Endpoint:oss-cn-beijing-internal.aliyuncs.com

2、简单访问

  • 此次测试写在外网,endpoint使用外网endpoint(oss-cn-beijing.aliyuncs.com)
  • 虚拟托管访问方式:
  • S3支持路径(Path)请求风格和虚拟托管(Virtual Hosted)请求风格。虚拟托管请求风格是指将Bucket置于Host Header的访问方式。基于安全考虑,OSS仅支持虚拟托管访问方式。(https://help.aliyun.com/document_detail/389025.html)
  • NewSession的参数:S3ForcePathStyle: aws.Bool(false)
  • true代表使用路径(Path)请求风格,oss不支持,所有设置为false。其实默认就是false。
    代码给oss中的文件1.jpg预签名一个超时时间1分钟的地址,可以在浏览器上访问,一分钟后过期:
package main

import (
   "github.com/aws/aws-sdk-go/aws"
   "github.com/aws/aws-sdk-go/aws/credentials"
   "github.com/aws/aws-sdk-go/aws/session"
   "github.com/aws/aws-sdk-go/service/s3"
   "log"
   "time"
)

var (
   accessKey = "AccessKey ID"       //""
   secretKey = "AccessKey Secret" //""
   region    = "oss-cn-beijing"
   endpoint  = "oss-cn-beijing.aliyuncs.com"
   //timeout   time.Duration = time.Second * 5
)

func main() {
   sess, err := session.NewSession(&aws.Config{
      Credentials: credentials.NewStaticCredentials(accessKey, secretKey, ""),
      Endpoint:    aws.String(endpoint),
      Region:      aws.String(region),
      //minio:true,oss:false
      S3ForcePathStyle: aws.Bool(false),
   })
   if err != nil {
      panic(err)
   }
   svc := s3.New(sess)
   PreGetObj(svc, "bkt-bj1", "1.jpg")
}
func PreGetObj(svc *s3.S3, bucket, key string) {
   req, _ := svc.GetObjectRequest(&s3.GetObjectInput{
      Bucket: aws.String(bucket),
      Key:    aws.String(key),
   })
   urlStr, err := req.Presign(1 * time.Minute)

   if err != nil {
      log.Println("Failed to sign request", err)

      return
   }
   log.Println("The URL is", urlStr)
}

打印出来的地址,可以复制到浏览器中可以访问。
一分钟后再访问会提示如下:(拒绝访问)

This XML file does not appear to have any style information associated with it. The document tree is shown below.
<Error>
<Code>AccessDenied</Code>
<Message>Request has expired.</Message>
<RequestId>62DF47196AD6D538304DFD0F</RequestId>
<HostId>bkt-bj1.oss-cn-beijing.aliyuncs.com</HostId>
<Expires>20220726T014449Z</Expires>
<ServerTime>20220726T014457Z</ServerTime>
<X-Amz-Expires>60</X-Amz-Expires>
</Error>