Generazione di un URL prefirmato per il caricamento di un oggetto - Amazon Simple Storage Service

Generazione di un URL prefirmato per il caricamento di un oggetto

Un URL prefirmato concede le credenziali d'accesso all'oggetto identificato nell'URL, purché il creatore dell'URL prefirmato disponga delle autorizzazioni per l'accesso a tale oggetto. In altre parole, se si riceve un URL prefirmato per caricare un oggetto, è possibile caricarlo solo se il creatore dell'URL prefirmato dispone delle autorizzazioni necessarie per caricare tale oggetto.

Per default, tutti gli oggetti e i bucket sono privati. Gli URL prefirmati sono utili se si desidera consentire a un utente/cliente di caricare un oggetto specifico nel bucket, senza concedergli credenziali o autorizzazioni di sicurezza per AWS.

Quando si crea un URL prefirmato, è necessario fornire le credenziali di sicurezza, quindi specificare un nome di bucket, una chiave dell'oggetto, un metodo HTTP (PUT per il caricamento degli oggetti), nonché una data e un'ora di scadenza. Gli URL prefirmati sono validi solo per la durata specificata. Vale a dire, è necessario avviare l'operazione prima della data e dell'ora di scadenza.

Se l'operazione è costituita da più fasi, ad esempio un caricamento in più parti, tutti le fasi devono essere avviate prima della scadenza. In caso contrario, quando Amazon S3 tenta di avviare una fase con un URL scaduto ricevi un errore.

È possibile utilizzare l'URL prefirmato più volte, fino alla data e all'ora di scadenza.

Accesso agli URL prefirmati

Poiché gli URL prefirmati consentono l'accesso ai tuoi bucket Amazon S3 a chiunque disponga dell'URL, ti consigliamo di proteggerli in modo appropriato. Per ulteriori informazioni sulla protezione di URL prefirmati, consulta la sezione Limitazione delle funzionalità degli URL prefirmati.

Qualsiasi utente che disponga di credenziali di sicurezza valide può creare un URL prefirmato. Tuttavia, per riuscire a caricare correttamente un oggetto, è necessario che l'URL prefirmato sia creato da un utente dotato dell'autorizzazione per eseguire l'operazione su cui si basa l'URL prefirmato. Per ulteriori informazioni, consulta Chi può creare un URL prefirmato.

Generazione di un URL prefirmato per il caricamento di oggetti

Puoi generare un URL prefirmato a livello di programmazione tramite gli SDK AWS per .NET, Java, Ruby, JavaScript, PHP e Python.

Puoi utilizzare l'SDK AWS per generare un URL prefirmato, utilizzabile da te o da chiunque disponga dell'URL, per caricare un oggetto in Amazon S3. Quando carichi un oggetto nel bucket utilizzando l'URL, Amazon S3 crea l'oggetto in un bucket specifico. Se nel bucket esiste già un oggetto con la stessa chiave specificata nell'URL prefirmato, Amazon S3 sostituisce l'oggetto esistente con l'oggetto caricato.

Se utilizzi Microsoft Visual Studio, puoi generare un URL di un oggetto prefirmato senza scrivere codice tramite AWS Explorer in AWS Toolkit for Visual Studio. Chiunque riceva URL prefirmati può quindi caricare un oggetto a livello di codice. Per ulteriori informazioni, consulta la sezione Utilizzo di Amazon S3 da AWS Explorer nella Guida per l'utente di AWS Toolkit for Visual Studio.

Per istruzioni su come installare AWS Explorer, consulta la sezione Sviluppo con Amazon S3 utilizzando SDK AWS ed explorer.

Negli esempi seguenti viene illustrato come caricare oggetti utilizzando URL prefirmati.

Gli esempi di codice seguenti mostrano come creare un URL prefirmato per S3 e caricare un oggetto.

Go
SDK per Go V2
Nota

Ulteriori informazioni su GitHub. Trova l'esempio completo e scopri di più sulla configurazione e l'esecuzione nel Repository di esempi di codice AWS.

// Get a presigned URL for the object. // In order to get a presigned URL for an object, you must // create a Presignclient fmt.Println("Create Presign client") presignClient := s3.NewPresignClient(&client) presignParams := &s3.GetObjectInput{ Bucket: aws.String(name), Key: aws.String("path/myfile.jpg"), } // Apply an expiration via an option function presignDuration := func(po *s3.PresignOptions) { po.Expires = 5 * time.Minute } presignResult, err := presignClient.PresignGetObject(context.TODO(), presignParams, presignDuration) if err != nil { panic("Couldn't get presigned URL for GetObject") } fmt.Printf("Presigned URL For object: %s\n", presignResult.URL)
Java
SDK per Java 2.x
Nota

Ulteriori informazioni su GitHub. Trova l'esempio completo e scopri di più sulla configurazione e l'esecuzione nel Repository di esempi di codice AWS.

public static void signBucket(S3Presigner presigner, String bucketName, String keyName) { try { PutObjectRequest objectRequest = PutObjectRequest.builder() .bucket(bucketName) .key(keyName) .contentType("text/plain") .build(); PutObjectPresignRequest presignRequest = PutObjectPresignRequest.builder() .signatureDuration(Duration.ofMinutes(10)) .putObjectRequest(objectRequest) .build(); PresignedPutObjectRequest presignedRequest = presigner.presignPutObject(presignRequest); String myURL = presignedRequest.url().toString(); System.out.println("Presigned URL to upload a file to: " +myURL); System.out.println("Which HTTP method needs to be used when uploading a file: " + presignedRequest.httpRequest().method()); // Upload content to the Amazon S3 bucket by using this URL. URL url = presignedRequest.url(); // Create the connection and use it to upload the new object by using the presigned URL. HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setDoOutput(true); connection.setRequestProperty("Content-Type","text/plain"); connection.setRequestMethod("PUT"); OutputStreamWriter out = new OutputStreamWriter(connection.getOutputStream()); out.write("This text was uploaded as an object by using a presigned URL."); out.close(); connection.getResponseCode(); System.out.println("HTTP response code is " + connection.getResponseCode()); } catch (S3Exception | IOException e) { e.getStackTrace(); } }
JavaScript
SDK per JavaScript v3
Nota

Ulteriori informazioni su GitHub. Trova l'esempio completo e scopri di più sulla configurazione e l'esecuzione nel Repository di esempi di codice AWS.

Crea il client.

// Create service client module using ES6 syntax. import { S3Client } from "@aws-sdk/client-s3"; // Set the AWS Region. const REGION = "us-east-1"; // Create an Amazon S3 service client object. const s3Client = new S3Client({ region: REGION }); export { s3Client };

Crea un URL prefirmato per caricare un oggetto in un bucket.

// Import the required AWS SDK clients and commands for Node.js import { CreateBucketCommand, DeleteObjectCommand, PutObjectCommand, DeleteBucketCommand } from "@aws-sdk/client-s3"; import { s3Client } from "./libs/s3Client.js"; // Helper function that creates an Amazon S3 service client module. import { getSignedUrl } from "@aws-sdk/s3-request-presigner"; import fetch from "node-fetch"; // Set parameters // Create a random name for the Amazon Simple Storage Service (Amazon S3) bucket and key export const bucketParams = { Bucket: `test-bucket-${Math.ceil(Math.random() * 10 ** 10)}`, Key: `test-object-${Math.ceil(Math.random() * 10 ** 10)}`, Body: "BODY" }; export const run = async () => { try { // Create an S3 bucket. console.log(`Creating bucket ${bucketParams.Bucket}`); await s3Client.send(new CreateBucketCommand({ Bucket: bucketParams.Bucket })); console.log(`Waiting for "${bucketParams.Bucket}" bucket creation...`); } catch (err) { console.log("Error creating bucket", err); } try { // Create a command to put the object in the S3 bucket. const command = new PutObjectCommand(bucketParams); // Create the presigned URL. const signedUrl = await getSignedUrl(s3Client, command, { expiresIn: 3600, }); console.log( `\nPutting "${bucketParams.Key}" using signedUrl with body "${bucketParams.Body}" in v3` ); console.log(signedUrl); const response = await fetch(signedUrl, {method: 'PUT', body: bucketParams.Body}); console.log( `\nResponse returned by signed URL: ${await response.text()}\n` ); } catch (err) { console.log("Error creating presigned URL", err); } try { // Delete the object. console.log(`\nDeleting object "${bucketParams.Key}"} from bucket`); await s3Client.send( new DeleteObjectCommand({ Bucket: bucketParams.Bucket, Key: bucketParams.Key }) ); } catch (err) { console.log("Error deleting object", err); } try { // Delete the S3 bucket. console.log(`\nDeleting bucket ${bucketParams.Bucket}`); await s3Client.send( new DeleteBucketCommand({ Bucket: bucketParams.Bucket }) ); } catch (err) { console.log("Error deleting bucket", err); } }; run();

Crea un URL prefirmato per scaricare un oggetto da un bucket.

// Import the required AWS SDK clients and commands for Node.js import { CreateBucketCommand, PutObjectCommand, GetObjectCommand, DeleteObjectCommand, DeleteBucketCommand } from "@aws-sdk/client-s3"; import { s3Client } from "./libs/s3Client.js"; // Helper function that creates an Amazon S3 service client module. import { getSignedUrl } from "@aws-sdk/s3-request-presigner"; const fetch = require("node-fetch"); // Set parameters // Create a random names for the S3 bucket and key. export const bucketParams = { Bucket: `test-bucket-${Math.ceil(Math.random() * 10 ** 10)}`, Key: `test-object-${Math.ceil(Math.random() * 10 ** 10)}`, Body: "BODY" }; export const run = async () => { // Create an S3 bucket. try { console.log(`Creating bucket ${bucketParams.Bucket}`); const data = await s3Client.send( new CreateBucketCommand({ Bucket: bucketParams.Bucket }) ); return data; // For unit tests. console.log(`Waiting for "${bucketParams.Bucket}" bucket creation...\n`); } catch (err) { console.log("Error creating bucket", err); } // Put the object in the S3 bucket. try { console.log(`Putting object "${bucketParams.Key}" in bucket`); const data = await s3Client.send( new PutObjectCommand({ Bucket: bucketParams.Bucket, Key: bucketParams.Key, Body: bucketParams.Body, }) ); return data; // For unit tests. } catch (err) { console.log("Error putting object", err); } // Create a presigned URL. try { // Create the command. const command = new GetObjectCommand(bucketParams); // Create the presigned URL. const signedUrl = await getSignedUrl(s3Client, command, { expiresIn: 3600, }); console.log( `\nGetting "${bucketParams.Key}" using signedUrl with body "${bucketParams.Body}" in v3` ); console.log(signedUrl); const response = await fetch(signedUrl); console.log( `\nResponse returned by signed URL: ${await response.text()}\n` ); } catch (err) { console.log("Error creating presigned URL", err); } // Delete the object. try { console.log(`\nDeleting object "${bucketParams.Key}"} from bucket`); const data = await s3Client.send( new DeleteObjectCommand({ Bucket: bucketParams.Bucket, Key: bucketParams.Key }) ); return data; // For unit tests. } catch (err) { console.log("Error deleting object", err); } // Delete the S3 bucket. try { console.log(`\nDeleting bucket ${bucketParams.Bucket}`); const data = await s3Client.send( new DeleteBucketCommand({ Bucket: bucketParams.Bucket, Key: bucketParams.Key }) ); return data; // For unit tests. } catch (err) { console.log("Error deleting object", err); } }; run();
Python
SDK per Python (Boto3)
Nota

Ulteriori informazioni su GitHub. Trova l'esempio completo e scopri di più sulla configurazione e l'esecuzione nel Repository di esempi di codice AWS.

Genera un URL prefirmato in grado di eseguire un'operazione S3 per un periodo di tempo limitato. Utilizza il pacchetto Requests per effettuare una richiesta con l'URL.

import argparse import logging import boto3 from botocore.exceptions import ClientError import requests logger = logging.getLogger(__name__) def generate_presigned_url(s3_client, client_method, method_parameters, expires_in): """ Generate a presigned Amazon S3 URL that can be used to perform an action. :param s3_client: A Boto3 Amazon S3 client. :param client_method: The name of the client method that the URL performs. :param method_parameters: The parameters of the specified client method. :param expires_in: The number of seconds the presigned URL is valid for. :return: The presigned URL. """ try: url = s3_client.generate_presigned_url( ClientMethod=client_method, Params=method_parameters, ExpiresIn=expires_in ) logger.info("Got presigned URL: %s", url) except ClientError: logger.exception( "Couldn't get a presigned URL for client method '%s'.", client_method) raise return url def usage_demo(): logging.basicConfig(level=logging.INFO, format='%(levelname)s: %(message)s') print('-'*88) print("Welcome to the Amazon S3 presigned URL demo.") print('-'*88) parser = argparse.ArgumentParser() parser.add_argument('bucket', help="The name of the bucket.") parser.add_argument( 'key', help="For a GET operation, the key of the object in Amazon S3. For a " "PUT operation, the name of a file to upload.") parser.add_argument( 'action', choices=('get', 'put'), help="The action to perform.") args = parser.parse_args() s3_client = boto3.client('s3') client_action = 'get_object' if args.action == 'get' else 'put_object' url = generate_presigned_url( s3_client, client_action, {'Bucket': args.bucket, 'Key': args.key}, 1000) print("Using the Requests package to send a request to the URL.") response = None if args.action == 'get': response = requests.get(url) elif args.action == 'put': print("Putting data to the URL.") try: with open(args.key, 'r') as object_file: object_text = object_file.read() response = requests.put(url, data=object_text) except FileNotFoundError: print(f"Couldn't find {args.key}. For a PUT operation, the key must be the " f"name of a file that exists on your computer.") if response is not None: print("Got response:") print(f"Status: {response.status_code}") print(response.text) print('-'*88) if __name__ == '__main__': usage_demo()

Genera una richiesta POST prefirmata per caricare un file.

class BucketWrapper: """Encapsulates S3 bucket actions.""" def __init__(self, bucket): """ :param bucket: A Boto3 Bucket resource. This is a high-level resource in Boto3 that wraps bucket actions in a class-like structure. """ self.bucket = bucket self.name = bucket.name def generate_presigned_post(self, object_key, expires_in): """ Generate a presigned Amazon S3 POST request to upload a file. A presigned POST can be used for a limited time to let someone without an AWS account upload a file to a bucket. :param object_key: The object key to identify the uploaded object. :param expires_in: The number of seconds the presigned POST is valid. :return: A dictionary that contains the URL and form fields that contain required access data. """ try: response = self.bucket.meta.client.generate_presigned_post( Bucket=self.bucket.name, Key=object_key, ExpiresIn=expires_in) logger.info("Got presigned POST URL: %s", response['url']) except ClientError: logger.exception( "Couldn't get a presigned POST URL for bucket '%s' and object '%s'", self.bucket.name, object_key) raise return response
Ruby
SDK per Ruby
Nota

Ulteriori informazioni su GitHub. Trova l'esempio completo e scopri di più sulla configurazione e l'esecuzione nel Repository di esempi di codice AWS.

require "aws-sdk-s3" require "net/http" # Creates a presigned URL that can be used to upload content to an object. # # @param bucket [Aws::S3::Bucket] An existing Amazon S3 bucket. # @param object_key [String] The key to give the uploaded object. # @return [URI, nil] The parsed URI if successful; otherwise nil. def get_presigned_url(bucket, object_key) url = bucket.object(object_key).presigned_url(:put) puts "Created presigned URL: #{url}." URI(url) rescue Aws::Errors::ServiceError => e puts "Couldn't create presigned URL for #{bucket.name}:#{object_key}. Here's why: #{e.message}" end def run_demo bucket_name = "doc-example-bucket" object_key = "my-file.txt" object_content = "This is the content of my-file.txt." bucket = Aws::S3::Bucket.new(bucket_name) presigned_url = get_presigned_url(bucket, object_key) return unless presigned_url response = Net::HTTP.start(presigned_url.host) do |http| http.send_request("PUT", presigned_url.request_uri, object_content, "content_type" => "") end case response when Net::HTTPSuccess puts "Content uploaded!" else puts response.value end end run_demo if $PROGRAM_NAME == __FILE__