Ao compartilhar grandes conjuntos de dados, ative o modo Pay-by-requester no bucket. Esse recurso transfere os custos de acesso aos dados, como taxas de transferência e requisição, para quem solicita os dados. O proprietário do bucket arca apenas com as taxas de armazenamento e outros custos fixos. Quando o Pay-by-requester está ativado em um bucket, o acesso anônimo é desabilitado e todas as requisições exigem autenticação.
Aplicabilidade
O Pay-by-requester só pode ser ativado em buckets que possuem um atributo de região.
Funcionamento
O OSS processa as requisições com base na seguinte lógica:
Se uma requisição incluir o cabeçalho
x-oss-request-payer, o OSS autenticará o solicitante. Caso a autenticação seja bem-sucedida, o solicitante será cobrado pelas taxas de transferência de dados e de requisição.-
Se uma requisição não incluir o cabeçalho
x-oss-request-payer:Caso o solicitante seja o proprietário do bucket, a requisição será processada normalmente e o proprietário do bucket arcará com todas as taxas.
Caso o solicitante não seja o proprietário do bucket, a requisição será rejeitada.
Configuração pelo proprietário do bucket
Etapa 1: Ativar o Pay-by-requester
Faça login no console do OSS.
Clique em Buckets e, em seguida, clique em nome do bucket desejado.
No painel de navegação à esquerda, escolha .
Na página Pay-by-requester, ative a chave Pay-by-requester.
Na caixa de diálogo exibida, clique em OK.
Etapa 2: Conceder acesso ao solicitante
Utilize uma Bucket Policy para conceder permissões de acesso ao solicitante. Sem essas permissões, o solicitante não consegue acessar os dados.
Na página Buckets, clique em nome do bucket desejado.
No painel de navegação à esquerda, escolha .
Na página Bucket Policy, na aba Add in GUI, clique em Authorize.
No painel Authorize, configure a política. Em Authorized User, selecione Other Accounts e insira o ID da conta Alibaba Cloud do solicitante ou o ARN da função RAM. O formato é
arn:sts::{RoleOwnerUid}:assumed-role/{RoleName}/{RoleSessionName}.Clique em OK.
Acesso aos dados como solicitante
Como solicitante, você deve ter ativado o OSS e indicar na sua requisição que arcará com as taxas resultantes ao acessar um bucket com o Pay-by-requester ativado.
Console
Faça login no console do OSS.
No painel de navegação à esquerda, clique em sinal de mais (+) ao lado de Favorite Paths.
-
Na caixa de diálogo Add Favorite Paths, configure os parâmetros conforme descrito na tabela a seguir.
Parâmetro
Descrição
Adding method
Selecione Add from other authorized buckets para adicionar o bucket autorizado aos seus caminhos favoritos.
Region
Selecione a região onde o bucket autorizado está localizado.
Bucket
Insira o nome do bucket autorizado.
Pay-by-requester
Selecione I understand and agree para confirmar seu acordo em realizar o pagamento. Em seguida, você poderá acessar os recursos especificados no caminho do arquivo. Você será faturado pelas taxas incorridas no acesso ao bucket, como taxas de transferência de dados e de requisição.
SDK
O código a seguir exemplifica como especificar que terceiros serão cobrados ao acessarem objetos por meio das operações PutObject, GetObject e DeleteObject. Use esse método para especificar que terceiros serão cobrados ao executarem operações de leitura e gravação em objetos chamando outras operações da API de maneira semelhante.
Quando um terceiro executa uma operação de objeto, ele deve incluir o parâmetro x-oss-request-payer:requester no cabeçalho HTTP. Caso contrário, a requisição falhará.
Java
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.*;
import java.io.ByteArrayInputStream;
public class Demo {
public static void main(String[] args) throws Exception{
// In this example, the endpoint of the China (Hangzhou) region is used. Specify your actual endpoint. For more information about the endpoints of other regions, see Regions and endpoints.
String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
// Obtain access credentials from environment variables. Before you run the sample code, make sure that the OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET environment variables are configured.
EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
// Specify the name of the bucket. Example: examplebucket.
String bucketName = "examplebucket";
// Specify the full path of the object. Example: exampledir/exampleobject.txt. Do not include the bucket name in the full path.
String objectName = "exampledir/exampleobject.txt";
Payer payer = Payer.Requester;
// Specify the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set the region to cn-hangzhou.
String region = "cn-hangzhou";
// Create an OSS Client instance.
// Call the shutdown method to release associated resources when the OSS Client is no longer in use.
ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);
OSS ossClient = OSSClientBuilder.create()
.endpoint(endpoint)
.credentialsProvider(credentialsProvider)
.clientConfiguration(clientBuilderConfiguration)
.region(region)
.build();
try {
// Specify the payer when a third party calls the PutObject operation.
String content = "hello";
PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, new ByteArrayInputStream(content.getBytes()));
putObjectRequest.setRequestPayer(payer);
ossClient.putObject(putObjectRequest);
// Specify the payer when a third party calls the GetObject operation.
GetObjectRequest getObjectRequest = new GetObjectRequest(bucketName, objectName);
getObjectRequest.setRequestPayer(payer);
OSSObject ossObject = ossClient.getObject(getObjectRequest);
ossObject.close();
// Specify the payer when a third party calls the DeleteObject operation.
GenericRequest genericRequest = new GenericRequest(bucketName, objectName);
genericRequest.setRequestPayer(payer);
ossClient.deleteObject(genericRequest);
} 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 {
// Shut down the OSSClient instance.
if (ossClient != null) {
ossClient.shutdown();
}
}
}
}
Python
# -*- coding: utf-8 -*-
import oss2
from oss2.credentials import EnvironmentVariableCredentialsProvider
from oss2.headers import OSS_REQUEST_PAYER
# Obtain access credentials from environment variables. Before you run the sample code, make sure that the OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET environment variables are set.
auth = oss2.ProviderAuthV4(EnvironmentVariableCredentialsProvider())
# Specify the endpoint of the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set the endpoint to https://oss-cn-hangzhou.aliyuncs.com.
endpoint = "https://oss-cn-hangzhou.aliyuncs.com"
# Specify the ID of the region that maps to the endpoint. Example: cn-hangzhou. This parameter is required if you use the signature algorithm V4.
region = "cn-hangzhou"
# Specify the name of your bucket.
bucket = oss2.Bucket(auth, endpoint, "yourBucketName", region=region)
# Specify the full path of the object. Do not include the bucket name in the full path. Example: exampledir/exampleobject.txt.
object_name = 'exampledir/exampleobject.txt'
headers = dict()
headers[OSS_REQUEST_PAYER] = "requester"
# Specify the x-oss-request-payer header in the request to upload the object.
result = bucket.put_object(object_name, 'test-content', headers=headers)
# Specify the x-oss-request-payer header in the request to download the object.
result = bucket.get_object(object_name, headers=headers)
# Specify the x-oss-request-payer header in the request to delete the object.
result = bucket.delete_object(object_name, headers=headers);
Go
package main
import (
"fmt"
"io"
"os"
"strings"
"github.com/aliyun/aliyun-oss-go-sdk/oss"
)
func main() {
// Obtain access credentials from environment variables. Before you run the sample code, make sure that the OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET environment variables are set.
provider, err := oss.NewEnvironmentVariableCredentialsProvider()
if err != nil {
fmt.Println("Error:", err)
os.Exit(-1)
}
// Create an OSSClient instance.
// Specify the endpoint of the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set the endpoint to https://oss-cn-hangzhou.aliyuncs.com. Specify your actual endpoint.
// Specify the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set the region to cn-hangzhou. Specify the actual region.
clientOptions := []oss.ClientOption{oss.SetCredentialsProvider(&provider)}
clientOptions = append(clientOptions, oss.Region("yourRegion"))
// Specify the version of the signature algorithm.
clientOptions = append(clientOptions, oss.AuthVersion(oss.AuthV4))
payerClient, err := oss.New("yourEndpoint", "", "", clientOptions...)
if err != nil {
fmt.Println("New Error:", err)
os.Exit(-1)
}
// Specify the name of the bucket.
payerBucket, err := payerClient.Bucket("examplebucket")
if err != nil {
fmt.Println("Error:", err)
os.Exit(-1)
}
// If pay-by-requester is enabled, external requesters must set the oss.RequestPayer(oss.Requester) parameter to access authorized content.
// If pay-by-requester is not enabled, external requesters are not required to include the oss.RequestPayer(oss.Requester) parameter to access the authorized content.
// Upload an object.
// Specify the full path of the object. Do not include the bucket name in the full path. Example: exampledir/exampleobject.txt.
key := "exampledir/exampleobject.txt"
err = payerBucket.PutObject(key, strings.NewReader("objectValue"), oss.RequestPayer("requester"))
if err != nil {
fmt.Println("put Error:", err)
os.Exit(-1)
}
// List all objects in the bucket.
lor, err := payerBucket.ListObjects(oss.RequestPayer(oss.Requester))
if err != nil {
fmt.Println("Error:", err)
os.Exit(-1)
}
// Display the names of objects in the bucket.
for _, l := range lor.Objects {
fmt.Println("the Key name is :", l.Key)
}
// Download the object.
body, err := payerBucket.GetObject(key, oss.RequestPayer(oss.Requester))
if err != nil {
fmt.Println("Get Error:", err)
os.Exit(-1)
}
// You must close the obtained stream after the object is read. Otherwise, connection leaks may occur. Consequently, no connections are available and an exception occurs.
defer body.Close()
// Read and display the obtained content.
data, err := io.ReadAll(body)
if err != nil {
fmt.Println("Error:", err)
os.Exit(-1)
}
fmt.Println("data:", string(data))
// Delete the object.
err = payerBucket.DeleteObject(key, oss.RequestPayer(oss.Requester))
if err != nil {
fmt.Println("Error:", err)
os.Exit(-1)
}
}
Node.js
const OSS = require('ali-oss');
const bucket = 'bucket-name';
const payer = 'Requester';
const client = new OSS({
// Set region to the region where the bucket is located. For example, if the bucket is in the China (Hangzhou) region, set region to oss-cn-hangzhou.
region: 'yourregion',
// Obtain access credentials from environment variables. Before running the sample code, make sure the OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET environment variables are set.
accessKeyId: process.env.OSS_ACCESS_KEY_ID,
accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET,
authorizationV4: true,
// Set bucket to your bucket name.
bucket: 'yourBucketName',
});
async function main() {
await put();
await get();
await del();
}
async function put() {
const result = await client.putBucketRequestPayment(bucket, payer);
console.log('putBucketRequestPayment:', result);
// Specify the payer for the PutObject operation.
const response = await client.put('fileName', path.normalize('D:\\localpath\\examplefile.txt'), {
headers: {
'x-oss-request-payer': 'requester'
}
});
console.log('put:', response);
}
async function get() {
const result = await client.putBucketRequestPayment(bucket, payer);
console.log('putBucketRequestPayment:', result);
// Specify the payer for the GetObject operation.
const response = await client.get('fileName', {
headers: {
'x-oss-request-payer': 'requester'
}
});
console.log('get:', response);
}
async function del() {
const result = await client.putBucketRequestPayment(bucket, payer);
console.log('putBucketRequestPayment:', result);
// Specify the payer for the DeleteObject operation.
const response = await client.delete('fileName', {
headers: {
'x-oss-request-payer': 'requester'
}
});
console.log('delete:', response);
}
main();
C#
using System;
using System.IO;
using System.Text;
using Aliyun.OSS;
using Aliyun.OSS.Common;
namespace Samples
{
public class Program
{
public static void Main(string[] args)
{
// Specify the endpoint of the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set the endpoint to https://oss-cn-hangzhou.aliyuncs.com.
var endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
// Obtain access credentials from environment variables. Before you run the sample code, make sure that the OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET environment variables are set.
var accessKeyId = Environment.GetEnvironmentVariable("OSS_ACCESS_KEY_ID");
var accessKeySecret = Environment.GetEnvironmentVariable("OSS_ACCESS_KEY_SECRET");
// Specify the name of the bucket. Example: examplebucket.
var bucketName = "examplebucket";
var objectName = "example.txt";
var objectContent = "More than just cloud.";
// Specify the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set the region to cn-hangzhou.
const string region = "cn-hangzhou";
// Create a ClientConfiguration instance and modify parameters as required.
var conf = new ClientConfiguration();
// Use the signature algorithm V4.
conf.SignatureVersion = SignatureVersion.V4;
// Create an OSSClient instance.
var client = new OssClient(endpoint, accessKeyId, accessKeySecret, conf);
try
{
byte[] binaryData = Encoding.ASCII.GetBytes(objectContent);
MemoryStream requestContent = new MemoryStream(binaryData);
// Specify the payer when a third party calls the PutObject operation.
var putRequest = new PutObjectRequest(bucketName, objectName, requestContent);
putRequest.RequestPayer = RequestPayer.Requester;
var result = client.PutObject(putRequest);
// Specify the payer when a third party calls the GetObject operation.
var getRequest = new GetObjectRequest(bucketName, objectName);
getRequest.RequestPayer = RequestPayer.Requester;
var getResult = client.GetObject(getRequest);
// Specify the payer when a third party calls the DeleteObject operation.
var delRequest = new DeleteObjectRequest(bucketName, objectName);
delRequest.RequestPayer = RequestPayer.Requester;
client.DeleteObject(delRequest);
}
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);
}
}
}
}
PHP
<?php
if (is_file(__DIR__ . '/../autoload.php')) {
require_once __DIR__ . '/../autoload.php';
}
if (is_file(__DIR__ . '/../vendor/autoload.php')) {
require_once __DIR__ . '/../vendor/autoload.php';
}
use OSS\Credentials\EnvironmentVariableCredentialsProvider;
use OSS\OssClient;
use OSS\Core\OssException;
// Obtain access credentials from environment variables. Before you run the sample code, make sure that the OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET environment variables are set.
$provider = new EnvironmentVariableCredentialsProvider();
// In this example, the endpoint of the China (Hangzhou) region is used. Specify your actual endpoint.
$endpoint = "http://oss-cn-hangzhou.aliyuncs.com";
// Specify the name of the bucket. Example: examplebucket.
$bucket= "examplebucket";
// Specify the full path of the object. Do not include the bucket name in the full path. Example: exampledir/exampleobject.txt.
$object = "exampledir/exampleobject.txt";
// Enable pay-by-requester for the bucket.
$options = array(
OssClient::OSS_HEADERS => array(
OssClient::OSS_REQUEST_PAYER => 'requester',
));
try {
$config = array(
"provider" => $provider,
"endpoint" => $endpoint,
"signatureVersion" => OssClient::OSS_SIGNATURE_VERSION_V4,
"region"=> "cn-hangzhou"
);
$ossClient = new OssClient($config);
// Specify the payer when a third party calls the PutObject operation.
$content = "hello";
$ossClient->putObject($bucket, $object, $content, $options);
// Specify the payer when a third party calls the GetObject operation.
$ossClient->getObject($bucket, $object, $options);
// Specify the payer when a third party calls the DeleteObject operation.
$ossClient->deleteObject($bucket, $object, $options);
} catch (OssException $e) {
printf(__FUNCTION__ . ": FAILED\n");
printf($e->getMessage() . "\n");
return;
}
print(__FUNCTION__ . ": OK" . "\n");
C++
#include <alibabacloud/oss/OssClient.h>
#include <fstream>
using namespace AlibabaCloud::OSS;
int main(void)
{
/* Initialize the OSS account information. */
/* Set yourEndpoint to the endpoint of the region where the bucket is located. For example, if the bucket is in the China (Hangzhou) region, set the endpoint to https://oss-cn-hangzhou.aliyuncs.com. */
std::string Endpoint = "yourEndpoint";
/* Set yourRegion to the region where the bucket is located. For example, if the bucket is in the China (Hangzhou) region, set the region to cn-hangzhou. */
std::string Region = "yourRegion";
/* Specify the name of the bucket that the requester wants to access. For example, examplebucket. */
std::string BucketName = "examplebucket";
/* Specify the full path of the object that the requester wants to access. The full path cannot contain the bucket name. For example, exampledir/exampleobject.txt. */
std::string ObjectName = "exampleobject.txt";
/* Initialize network resources. */
InitializeSdk();
ClientConfiguration conf;
conf.signatureVersion = SignatureVersionType::V4;
/* Obtain access credentials from environment variables. Before you run this sample code, make sure that the requester's OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET are set as environment variables. */
auto credentialsProvider = std::make_shared<EnvironmentVariableCredentialsProvider>();
OssClient client(Endpoint, credentialsProvider, conf);
client.SetRegion(Region);
/* Set the pay-by-requester mode when you upload a file. */
std::shared_ptr<std::iostream> content = std::make_shared<std::stringstream>();
*content << "test cpp sdk";
PutObjectRequest putrequest(BucketName, ObjectName, content);
putrequest.setRequestPayer(RequestPayer::Requester);
auto putoutcome = client.PutObject(putrequest);
/* Set the pay-by-requester mode when you download a file to the local memory. */
GetObjectRequest getrequest(BucketName, ObjectName);
getrequest.setRequestPayer(RequestPayer::Requester);
auto getoutcome = client.GetObject(getrequest);
/* Set the pay-by-requester mode when you delete a file. */
DeleteObjectRequest delrequest(BucketName, ObjectName);
delrequest.setRequestPayer(RequestPayer::Requester);
auto deloutcome = client.DeleteObject(delrequest);
/* Release network resources. */
ShutdownSdk();
return 0;
}
ossutil
É necessário instalar o ossutil antes de utilizá-lo.
Por exemplo, para baixar um objeto usando o comando cp, especifique o parâmetro --request-payer=requester.
ossutil cp oss://examplebucket/examplefile.txt /localpath --request-payer=requester
API
Ao fazer uma requisição direta à API REST, inclua o cabeçalho x-oss-request-payer: requester na sua requisição. Certifique-se de que esse cabeçalho também esteja incluído no cálculo da assinatura. Para obter mais informações sobre o cálculo da assinatura, consulte Incluir uma assinatura no cabeçalho.
GET /oss.jpg HTTP/1.1
Host: oss-example.oss-cn-hangzhou.aliyuncs.com
Date: Fri, 24 Feb 2012 06:38:30 GMT
Authorization: OSS4-HMAC-SHA256 Credential=LTAI********************/20250417/cn-hangzhou/oss/aliyun_v4_request,Signature=a7c3554c729d71929e0b84489addee6b2e8d5cb48595adfc51868c299c0c218e
Considerações de produção
-
Faturamento de acesso via função RAM: Quando um solicitante acessa dados assumindo uma função RAM da Alibaba Cloud, a conta à qual a função RAM pertence paga pela requisição.
Prática incorreta: Permitir que os solicitantes assumam uma função RAM da conta do proprietário do bucket para obter permissões de acesso. Nesse cenário, todas as requisições são executadas como se fossem do proprietário do bucket, e as taxas de requisição e transferência de dados resultantes são cobradas dele. Essa prática não transfere os custos para o solicitante.
Prática correta: Conceder permissões de acesso diretamente aos solicitantes usando uma Bucket Policy.
-
Armadilhas de url pré-assinada:
Prática incorreta: O proprietário do bucket usa suas credenciais de acesso (um par AccessKey ou credenciais temporárias STS) para gerar e compartilhar uma url pré-assinada. Nesse caso, as requisições são feitas como se fossem do proprietário do bucket, e ele é cobrado pelas taxas associadas.
Prática correta: O solicitante usa suas próprias credenciais de acesso (um par AccessKey ou credenciais temporárias STS) para gerar uma url pré-assinada e inclui o parâmetro
x-oss-request-payer=requesterao gerar a url. Para obter mais informações sobre como calcular a assinatura, consulte Incluir uma assinatura na url. Quando essa url é compartilhada e utilizada, as taxas são cobradas do solicitante que a gerou.
Riscos de compatibilidade: A ativação do Pay-by-requester pode interferir no acesso anônimo necessário para hospedagem de sites estáticos, o que pode tornar seu site indisponível. Recomendamos implantar os recursos de frontend do seu site (HTML, CSS e JS) e os dados que exigem Pay-by-requester em buckets separados.
Faturamento
Antes de o Pay-by-requester ser ativado em um bucket, todas as taxas são pagas pelo proprietário do bucket. Após a ativação do Pay-by-requester, a conta do solicitante paga pelos seguintes itens faturáveis. A conta do proprietário do bucket continua sendo cobrada por todos os outros itens faturáveis. Para obter uma lista completa de itens faturáveis, consulte Preços do OSS.
|
Taxa |
Item faturável |
|
tráfego de saída pela internet |
|
|
tráfego de origem |
|
|
Requisições PUT |
|
|
Requisições GET |
|
|
recuperação de dados do Infrequent Access |
|
|
recuperação de dados do Archive Storage |