Al compartir grandes conjuntos de datos, puede habilitar el modo de pago por solicitante en un bucket. Esta función transfiere los costos de acceso a los datos, como las tarifas de transferencia y de solicitudes, al solicitante de los datos. El propietario del bucket solo es responsable de las tarifas de almacenamiento y otros costos fijos. Cuando se habilita el pago por solicitante en un bucket, se deshabilita el acceso anónimo y todas las solicitudes requieren autenticación.
Aplicabilidad
El pago por solicitante solo se puede habilitar en buckets que tienen un atributo de región.
Funcionamiento
OSS procesa las solicitudes según la siguiente lógica:
Si una solicitud incluye el encabezado
x-oss-request-payer, OSS autentica al solicitante. Si la autenticación es correcta, se cobran al solicitante las tarifas de transferencia de datos y de solicitudes.-
Si una solicitud no incluye el encabezado
x-oss-request-payer:Si el solicitante es el propietario del bucket, la solicitud se procesa con normalidad y se cobran todos los cargos al propietario del bucket.
Si el solicitante no es el propietario del bucket, la solicitud se rechaza.
Configuración del propietario del bucket
Paso 1: Habilitar el pago por solicitante
Inicie sesión en la consola de OSS.
Haga clic en Buckets y luego haga clic en el nombre del bucket de destino.
En el panel de navegación izquierdo, seleccione .
En la página Pay-by-requester, active el interruptor de Pay-by-requester.
En el cuadro de diálogo que aparece, haga clic en OK.
Paso 2: Otorgar acceso al solicitante
Utilice una Bucket Policy para otorgar permisos de acceso al solicitante. Sin estos permisos, el solicitante no podrá acceder a los datos.
En la página Buckets, haga clic en el nombre del bucket de destino.
En el panel de navegación izquierdo, seleccione .
En la página Bucket Policy, en la pestaña Add in GUI, haga clic en Authorize.
En el panel Authorize, configure la directiva. Para Authorized User, seleccione Other Accounts e introduzca el ID de cuenta de Alibaba Cloud del solicitante o el ARN del rol de RAM. El formato es
arn:sts::{RoleOwnerUid}:assumed-role/{RoleName}/{RoleSessionName}.Haga clic en OK.
Acceso a datos como solicitante
Como solicitante, debe haber activado OSS e indicar en su solicitud que pagará las tarifas resultantes al acceder a un bucket con el pago por solicitante habilitado.
Consola
Inicie sesión en la consola de OSS.
En el panel de navegación izquierdo, haga clic en el signo más (+) junto a Favorite Paths.
-
En el cuadro de diálogo Add Favorite Paths, configure los parámetros como se describe en la siguiente tabla.
Parámetro
Descripción
Adding method
Seleccione Add from other authorized buckets para agregar el bucket autorizado a sus rutas favoritas.
Region
Seleccione la región donde reside el bucket autorizado.
Bucket
Introduzca el nombre del bucket autorizado.
Pay-by-requester
Seleccione I understand and agree para confirmar su acuerdo de pago. Luego podrá acceder a los recursos especificados en la ruta del archivo. Se le facturarán los cargos incurridos por acceder al bucket, como las tarifas de transferencia de datos y de solicitudes.
SDK
El siguiente código proporciona un ejemplo de cómo especificar que se cobre a terceros cuando acceden a objetos mediante las operaciones PutObject, GetObject y DeleteObject. Puede usar este método para especificar que se cobre a terceros cuando realizan operaciones de lectura y escritura en objetos al llamar a otras operaciones de API de manera similar.
Cuando un tercero realiza una operación sobre un objeto, debe incluir el parámetro x-oss-request-payer:requester en el encabezado HTTP. De lo contrario, la solicitud fallará.
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
Debe install ossutil antes de poder utilizarlo.
Por ejemplo, para descargar un objeto mediante el comando cp, especifique el parámetro --request-payer=requester.
ossutil cp oss://examplebucket/examplefile.txt /localpath --request-payer=requester
API
Al realizar una solicitud directa a la API REST, incluya el encabezado x-oss-request-payer: requester en su solicitud. Asegúrese de que este encabezado también se incluya en el cálculo de la firma. Para obtener más información sobre el cálculo de la firma, consulte Include a signature in the header.
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
Consideraciones de producción
-
Facturación de acceso mediante un rol de RAM: Cuando un solicitante accede a los datos asumiendo un rol de RAM de Alibaba Cloud, la cuenta a la que pertenece el rol de RAM paga la solicitud.
Práctica incorrecta: Permitir que los solicitantes asuman un rol de RAM de la cuenta del propietario del bucket para obtener permisos de acceso. En este escenario, todas las solicitudes se ejecutan como el propietario del bucket, y las tarifas resultantes de solicitudes y transferencia de datos se cobran al propietario del bucket. Esta práctica no transfiere los costos al solicitante.
Práctica correcta: Otorgue permisos de acceso directamente a los solicitantes mediante una Bucket Policy.
-
Riesgos de las URL prefirmadas:
Práctica incorrecta: El propietario del bucket utiliza sus credenciales de acceso (un par de AccessKey o credenciales temporales de STS) para generar y compartir una URL prefirmada. En este caso, las solicitudes se realizan como el propietario del bucket, y se cobran los cargos asociados al propietario del bucket.
Práctica correcta: El solicitante utiliza sus propias credenciales de acceso (un par de AccessKey o credenciales temporales de STS) para generar una URL prefirmada e incluye el parámetro
x-oss-request-payer=requesteral generar la URL. Para obtener más información sobre cómo calcular la firma, consulte Include a signature in the URL. Cuando esta URL se comparte y se utiliza, los cargos se cobran al solicitante que la generó.
Riesgos de compatibilidad: Habilitar el pago por solicitante puede interferir con el acceso anónimo necesario para el hosting de sitios web estáticos, lo que podría causar que su sitio web deje de estar disponible. Le recomendamos desplegar los recursos de frontend de su sitio web (HTML, CSS y JS) y los datos que requieren pago por solicitante en buckets separados.
Facturación
Antes de habilitar el pago por solicitante en un bucket, el propietario del bucket paga todas las tarifas. Después de habilitar el pago por solicitante, la cuenta del solicitante paga los siguientes conceptos facturables. La cuenta del propietario del bucket continúa recibiendo cargos por todos los demás conceptos facturables. Para obtener una lista completa de los conceptos facturables, consulte Precios de OSS.
|
Tarifa |
Concepto facturable |
|
Tráfico saliente por Internet |
|
|
Tráfico de origen |
|
|
Solicitudes PUT |
|
|
Solicitudes GET |
|
|
Recuperación de datos de Infrequent Access |
|
|
Recuperación de datos de Archive Storage |