请求者付费

在共享大型数据集或向客户与合作伙伴交付生产数据等场景下,若希望将访问数据所产生的流量和请求费用等转移给请求者,可以为存储空间(Bucket)开启请求者付费模式。该模式会将数据访问成本(如流量、请求次数)完全由请求者承担,Bucket 拥有者则仅需支付存储等固定费用。

说明

无地域属性存储空间不支持开启请求者付费模式。

工作原理

请求者付费模式的核心是将特定操作的费用归属从 Bucket 拥有者转移到发起请求的请求者。开启请求者付费模式后,匿名访问将被禁用,所有请求必须经过身份验证。OSS 按以下逻辑处理请求:

  • 请求中包含 x-oss-request-payer: requester 请求头:OSS 对请求者进行身份验证,流量和请求等费用由请求者承担。

  • 请求中不包含 x-oss-request-payer: requester 请求头

    • 请求者为 Bucket 拥有者:请求成功,费用由 Bucket 所有者承担。

    • 请求者非 Bucket 拥有者:请求被拒绝。

Bucket 拥有者配置请求者付费

步骤一:开启请求者付费

控制台

  1. 登录OSS管理控制台

  2. 单击Bucket 列表,然后单击目标Bucket名称。

  3. 在左侧导航栏,选择Bucket 配置 > 请求者付费

  4. 请求者付费页面,打开请求者付费开关。

  5. 在弹出的对话框,单击确定

SDK

以下仅列举常见SDK的设置请求者付费模式的代码示例。关于其他SDK的设置请求者付费模式的代码示例,请参见SDK简介

import com.aliyun.oss.ClientBuilderConfiguration;
import com.aliyun.oss.OSS;
import com.aliyun.oss.common.auth.*;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.common.comm.SignVersion;
import com.aliyun.oss.model.*;

public class Demo {
    public static void main(String[] args) throws Exception{
        // Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
        String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
        // 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
        EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
        // 填写Bucket名称,例如examplebucket。
        String bucketName = "examplebucket";
        // 填写Bucket所在地域。以华东1(杭州)为例,Region填写为cn-hangzhou。
        String region = "cn-hangzhou";

        // 创建OSSClient实例。
        // 当OSSClient实例不再使用时,调用shutdown方法以释放资源。
        ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
        clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);
        OSS ossClient = OSSClientBuilder.create()
                .endpoint(endpoint)
                .credentialsProvider(credentialsProvider)
                .clientConfiguration(clientBuilderConfiguration)
                .region(region)
                .build();
        try {
            // 设置请求者付费模式。
            Payer payer = Payer.Requester;
            ossClient.setBucketRequestPayment(bucketName, payer);
        } catch (OSSException oe) {
            System.out.println("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            System.out.println("Error Message:" + oe.getErrorMessage());
            System.out.println("Error Code:" + oe.getErrorCode());
            System.out.println("Request ID:" + oe.getRequestId());
            System.out.println("Host ID:" + oe.getHostId());
        } catch (Throwable ce) {
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message:" + ce.getMessage());
        } finally {
            // 关闭OSSClient。
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }
}
const OSS = require('ali-oss')

const client = new OSS({
  // yourregion填写Bucket所在地域。以华东1(杭州)为例,Region填写为oss-cn-hangzhou。
  region: 'yourregion',
  // 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
  accessKeyId: process.env.OSS_ACCESS_KEY_ID,
  accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET,
  authorizationV4: true,
  // yourBucketName填写Bucket名称。
  bucket: 'yourBucketName',

});

async function setBucketRequestPayment(bucket, Payer) {
  try {
    // bucket填写需要设置请求者付费模式的存储空间名称。
    // Payer取值为Requester或BucketOwner。
    // Payer设置为Requester,表明该存储空间已开启请求者付费模式,由请求者支付读取存储空间(Bucket)内数据时产生的流量费用和请求费用。
    // Payer设置为BucketOwner,表明该存储空间不开启请求者付费模式(默认状态),即请求产生的费用由数据拥有者(BucketOwner)来支付。
    const result = await client.putBucketRequestPayment(bucket, Payer);
    console.log(result);
  } catch (e) {
    console.log(e);
  }
}

setBucketRequestPayment('bucketName', 'Requester')
using Aliyun.OSS;
using Aliyun.OSS.Common;

// yourEndpoint填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。
var endpoint = "yourEndpoint";
// 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
var accessKeyId = Environment.GetEnvironmentVariable("OSS_ACCESS_KEY_ID");
var accessKeySecret = Environment.GetEnvironmentVariable("OSS_ACCESS_KEY_SECRET");
// 填写Bucket名称。
var bucketName = "examplebucket";
// 填写Bucket所在地域对应的Region。以华东1(杭州)为例,Region填写为cn-hangzhou。
const string region = "cn-hangzhou";

// 创建ClientConfiguration实例,按照您的需要修改默认参数。
var conf = new ClientConfiguration();

// 设置v4签名。
conf.SignatureVersion = SignatureVersion.V4;

// 创建OssClient实例。
var client = new OssClient(endpoint, accessKeyId, accessKeySecret, conf);
client.SetRegion(region);
try
{
    // 设置请求者付费模式。
    var request = new SetBucketRequestPaymentRequest(bucketName, RequestPayer.Requester);
    client.SetBucketRequestPayment(request);
    Console.WriteLine("Set bucket:{0} RequestPayment succeeded ", bucketName);
}
catch (OssException ex)
{
    Console.WriteLine("Failed with error code: {0}; Error info: {1}. \nRequestID:{2}\tHostID:{3}",
        ex.ErrorCode, ex.Message, ex.RequestId, ex.HostId);
}
catch (Exception ex)
{
    Console.WriteLine("Failed with error info: {0}", ex.Message);
}
#include <alibabacloud/oss/OssClient.h>
using namespace AlibabaCloud::OSS;

int main(void)
{
    /*初始化OSS账号信息。*/
    
    /*yourEndpoint填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。*/
    std::string Endpoint = "yourEndpoint";
    
    / *yourRegion填写Bucket所在地域对应的Region。以华东1(杭州)为例,Region填写为cn - hangzhou。 * /
    std::string Region = "yourRegion";
    
    /*填写Bucket名称,例如examplebucket。*/
    std::string BucketName = "examplebucket";

    /*初始化网络等资源。*/
    InitializeSdk();

    ClientConfiguration conf;
    conf.signatureVersion = SignatureVersionType::V4;
    /* 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。*/
    auto credentialsProvider = std::make_shared<EnvironmentVariableCredentialsProvider>();
    OssClient client(Endpoint, credentialsProvider, conf);
    client.SetRegion(Region);

    /*设置请求者付费模式。*/
    SetBucketRequestPaymentRequest request(BucketName);
    request.setRequestPayer(RequestPayer::Requester);

    auto outcome = client.SetBucketRequestPayment(request);

    if (!outcome.isSuccess()) {
        /*异常处理。*/
        std::cout << "SetBucketRequestPayment fail" <<
        ",code:" << outcome.error().Code() <<
        ",message:" << outcome.error().Message() <<
        ",requestId:" << outcome.error().RequestId() << std::endl;
        return -1;
    }

    /*释放网络等资源。*/
    ShutdownSdk();
    return 0;
}
package main

import (
	"context"
	"flag"
	"log"

	"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss"
	"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss/credentials"
)

// 定义全局变量
var (
	region     string // 存储区域
	bucketName string // 存储空间名称
)

// init函数用于初始化命令行参数
func init() {
	flag.StringVar(&region, "region", "", "The region in which the bucket is located.")
	flag.StringVar(&bucketName, "bucket", "", "The name of the bucket.")
}

func main() {
	// 解析命令行参数
	flag.Parse()

	// 检查bucket名称是否为空
	if len(bucketName) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, bucket name required")
	}

	// 检查region是否为空
	if len(region) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, region required")
	}

	// 加载默认配置并设置凭证提供者和区域
	cfg := oss.LoadDefaultConfig().
		WithCredentialsProvider(credentials.NewEnvironmentVariableCredentialsProvider()).
		WithRegion(region)

	// 创建OSS客户端
	client := oss.NewClient(cfg)

	// 创建设置存储空间请求支付方式的请求
	putRequest := &oss.PutBucketRequestPaymentRequest{
		Bucket: oss.Ptr(bucketName), // 存储空间名称
		PaymentConfiguration: &oss.RequestPaymentConfiguration{
			Payer: oss.Requester, // 设置请求支付方为请求者
		},
	}

	// 发送设置存储空间请求支付方式的请求
	putResult, err := client.PutBucketRequestPayment(context.TODO(), putRequest)
	if err != nil {
		log.Fatalf("failed to put bucket request payment %v", err)
	}

	// 打印设置存储空间请求支付方式的结果
	log.Printf("put bucket request payment result:%#v\n", putResult)
}
import argparse
import alibabacloud_oss_v2 as oss

# 创建命令行参数解析器,并描述脚本用途:设置存储空间(Bucket)的请求支付配置
parser = argparse.ArgumentParser(description="put bucket request payment sample")

# 定义命令行参数,包括必需的区域、存储空间名称、可选的endpoint以及支付方
parser.add_argument('--region', help='The region in which the bucket is located.', required=True)
parser.add_argument('--bucket', help='The name of the bucket.', required=True)
parser.add_argument('--endpoint', help='The domain names that other services can use to access OSS')
parser.add_argument('--payer', help='Indicates who pays the download and request fees. Possible values: "Requester" or "BucketOwner"', required=True)

def main():
    # 解析命令行参数,获取用户输入的值
    args = parser.parse_args()

    # 从环境变量中加载访问凭证信息,用于身份验证
    credentials_provider = oss.credentials.EnvironmentVariableCredentialsProvider()

    # 使用SDK默认配置创建配置对象,并设置认证提供者
    cfg = oss.config.load_default()
    cfg.credentials_provider = credentials_provider

    # 设置配置对象的区域属性,根据用户提供的命令行参数
    cfg.region = args.region

    # 如果提供了自定义endpoint,则更新配置对象中的endpoint属性
    if args.endpoint is not None:
        cfg.endpoint = args.endpoint

    # 使用上述配置初始化OSS客户端,准备与OSS交互
    client = oss.Client(cfg)

    # 发送请求以设置指定存储空间的请求支付配置
    result = client.put_bucket_request_payment(oss.PutBucketRequestPaymentRequest(
            bucket=args.bucket,  # 存储空间名
            request_payment_configuration=oss.RequestPaymentConfiguration(
                payer=args.payer,  # 支付方,可以是 "Requester" 或 "BucketOwner"
            ),
    ))

    # 打印操作结果的状态码和请求ID,以便确认请求状态
    print(f'status code: {result.status_code},'
          f' request id: {result.request_id},'
          )

# 当此脚本被直接执行时,调用main函数开始处理逻辑
if __name__ == "__main__":
    main()  # 脚本入口点,控制程序流程从这里开始
<?php

require_once __DIR__ . '/../vendor/autoload.php'; // 引入自动加载文件,加载依赖库

use AlibabaCloud\Oss\V2 as Oss;

// 定义命令行参数描述
$optsdesc = [
    "region" => ['help' => 'The region in which the bucket is located.', 'required' => True], // 地域是必填项,存储空间所在的地域,例如 oss-cn-hangzhou。
    "endpoint" => ['help' => 'The domain names that other services can use to access OSS.', 'required' => False], // 访问域名是可选项,其他服务可以用来访问OSS的域名。
    "bucket" => ['help' => 'The name of the bucket', 'required' => True], // 存储空间名称是必填项。
];
$longopts = \array_map(function ($key) {
    return "$key:"; // 每个参数后面加冒号,表示需要值
}, array_keys($optsdesc));

// 解析命令行参数
$options = getopt("", $longopts); 

// 检查必填参数是否缺失
foreach ($optsdesc as $key => $value) {
    if ($value['required'] === True && empty($options[$key])) {
        $help = $value['help'];
        echo "Error: the following arguments are required: --$key, $help"; // 提示用户缺少必填参数
        exit(1); 
    }
}

// 获取命令行参数值
$region = $options["region"]; // 存储空间所在地域。
$bucket = $options["bucket"]; // 存储空间名称。

// 使用环境变量加载凭证信息(AccessKeyId 和 AccessKeySecret)
$credentialsProvider = new Oss\Credentials\EnvironmentVariableCredentialsProvider(); 

// 使用SDK的默认配置
$cfg = Oss\Config::loadDefault(); // 加载SDK的默认配置。
$cfg->setCredentialsProvider($credentialsProvider); // 设置凭证提供者。
$cfg->setRegion($region); // 设置地域。
if (isset($options["endpoint"])) {
    $cfg->setEndpoint($options["endpoint"]); // 如果提供了访问域名,则设置访问域名。
}

// 创建OSS客户端实例
$client = new Oss\Client($cfg); 

// 创建设置存储空间请求支付方式的请求对象
$request = new Oss\Models\PutBucketRequestPaymentRequest(
    $bucket,
    new Oss\Models\RequestPaymentConfiguration('Requester') 
);

// 调用putBucketRequestPayment方法设置存储空间请求支付方式
$result = $client->putBucketRequestPayment($request); 

// 打印返回结果
printf(
    'status code:' . $result->statusCode . PHP_EOL . // HTTP响应状态码。
    'request id:' . $result->requestId // 请求的唯一标识。
);

命令行工具ossutil

您可以使用命令行工具ossutil来设置请求者付费模式,ossutil的安装请参见安装ossutil

以下示例展示了如何为存储空间examplebucket 设置请求者付费模式。

ossutil api put-bucket-request-payment --bucket examplebucket --request-payment-configuration "{\"Payer\":\"Requester\"}"

如果您想了解该命令的更多信息,请参见put-bucket-request-payment

API

如果您的程序自定义要求较高,您可以直接发起REST API请求。直接发起REST API请求需要手动编写代码计算签名。更多信息,请参见PutBucketRequestPayment

步骤二:为请求者授予访问权限

通过Bucket PolicyRAM policy 精确授权请求者访问您的数据。切勿将自己账号下的 RAM 用户 AccessKey 提供给对方,否则费用依然请求费用仍需要您(请求者)来支付。

如果请求者通过扮演 Bucket 拥有者账户下的RAM角色访问开启了请求者付费模式的Bucket,那么产生的费用将由请求者的账户承担。

请求者携带x-oss-request-payer访问

当需要访问一个已开启请求者付费模式的 Bucket 时:必须携带x-oss-request-payer头信息以明确费用承担方。

  • 对于POST、GETHEAD请求,需在请求中包含x-oss-request-payer:requester信息。详情请参见签名版本4(推荐)

  • 对于签名URL,需在请求中包含x-oss-request-payer=requester信息。详情请参见签名版本4(推荐)

应用于生产环境

  • 预签名 URL 陷阱

    • 错误做法:由 Bucket 拥有者使用身份凭证(AccessKey 或 STS 临时凭证)生成预签名 URL 并对外分享。无论 URL 是否包含请求者付费参数,请求都会以Bucket 拥有者身份发起,相关费用由Bucket 拥有者承担。

    • 正确做法:由请求方使用身份凭证(AccessKey 或 STS 临时凭证)生成预签名 URL。

  • 兼容性风险:此功能与静态网站托管功能不兼容。开启请求者付费会破坏静态网站托管依赖的匿名访问机制,导致网站无法正常工作。

计费说明

Bucket开启请求者付费前,所有费用均由Bucket拥有者支付。Bucket开启请求者付费模式后,由Bucket拥有者支付的计费项将产生变化。Bucket拥有者以及请求者支付的详细说明如下:

费用

计费项

支付者

存储费用

标准存储(本地冗余)容量

Bucket拥有者

标准存储(同城冗余)容量

Bucket拥有者

低频访问(本地冗余)容量

Bucket拥有者

低频访问(同城冗余)容量

Bucket拥有者

归档(本地冗余)容量

Bucket拥有者

归档(同城冗余)容量

Bucket拥有者

冷归档(本地冗余)容量

Bucket拥有者

深度冷归档(本地冗余)容量

Bucket拥有者

低频访问(本地冗余)不足规定时长容量

Bucket拥有者

归档存储(本地冗余)不足规定时长容量

Bucket拥有者

归档存储(同城冗余)不足规定时长容量

Bucket拥有者

冷归档存储不足规定时长容量

Bucket拥有者

深度冷归档存储不足规定时长容量

Bucket拥有者

无地域属性存储容量

Bucket拥有者

流量费用

外网流出流量

请求者

外网流入流量

免费

内网流出流量

免费

内网流入流量

免费

CDN回源流出流量

请求者

跨区域复制流量

Bucket拥有者

请求费用

Put类型请求次数

请求者

Get类型请求次数

请求者

取回请求

Bucket拥有者

数据处理

图片处理

请求者

图片高级压缩

Bucket拥有者

视频截帧

请求者

Select扫描数据量

Bucket拥有者

低频访问数据取回容量

请求者

归档存储数据取回容量

请求者

归档直读数据取回容量

Bucket拥有者

冷归档存储数据取回容量

Bucket拥有者

深度冷归档存储数据取回容量

Bucket拥有者

对象标签费用

对象标签

Bucket拥有者

传输加速费用

传输加速AccM2MIn

Bucket拥有者

传输加速AccM2MOut

Bucket拥有者

传输加速AccM2OIn

Bucket拥有者

传输加速AccM2OOut

Bucket拥有者

传输加速AccO2MIn

Bucket拥有者

传输加速AccO2MOut

Bucket拥有者

传输加速AccO2OIn

Bucket拥有者

传输加速AccO2OOut

Bucket拥有者

临时存储费用

临时存储容量(本地冗余)

Bucket拥有者

DDoS防护费用

高防资源预留费用

Bucket拥有者

高防资源提前释放费用

Bucket拥有者

高防流量防护费用

Bucket拥有者

高防请求防护费用

Bucket拥有者

数据索引费用

Meta管理费

公测阶段,免费

Bucket查询费

公测阶段,免费

敏感数据保护费用

敏感数据保护扫描容量

Bucket拥有者

OSS加速器费用

OSS加速器容量

Bucket拥有者

OSS-HDFS元数据管理费用

元数据管理

Bucket拥有者

跨区域复制RTC费用

跨区域复制RTC

Bucket拥有者

说明

如果请求者未在请求中(GET、HEADPOST)声明请求者付费的请求头x-oss-request-payer,则由Bucket拥有者支付Put类和Get类请求次数费用。