使用适用于 Rust 的 AWS SDK 创建预签名 URL - 适用于 Rust 的 AWS SDK

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

使用适用于 Rust 的 AWS SDK 创建预签名 URL

您可以对某些 AWS API 操作的请求进行预签名,以便其他调用方以后无需提供自己的凭证即可使用该请求。

例如,假设 Jane 有权访问 Amazon Simple Storage Service(Amazon S3)对象,并希望临时与 Alejandro 分享对该对象的访问权限。Jane 可以生成预签名的 GetObject 请求来分享给 Alejandro,这样 Alejandro 就可以下载该对象而无需访问 Jane 的凭证,也无需拥有自己的凭证。预签名 URL 使用的凭证是 Jane 的,因为她是生成该 URL 的 AWS 用户。

要了解有关 Amazon S3 中预签名 URL 的更多信息,请参阅《Amazon Simple Storage Service 用户指南》中的使用预签名 URL

预签名基础知识

适用于 Rust 的 AWS SDK 在操作 fluent-builders 上提供了一个 presigned() 方法,可用于获取预签名请求。

以下示例展示了为 Amazon S3 创建预签名 GetObject 请求的过程。请求在创建后的 5 分钟内有效。

use std::time::Duration; use aws_config::BehaviorVersion; use aws_sdk_s3::presigning::PresigningConfig; let config = aws_config::defaults(BehaviorVersion::latest()) .load() .await; let s3 = aws_sdk_s3::Client::new(&config); let presigned = s3.get_object() .presigned( PresigningConfig::builder() .expires_in(Duration::from_secs(60 * 5)) .build() .expect("less than one week") ) .await?;

presigned() 方法返回 Result<PresignedRequest, SdkError<E, R>>

返回的 PresignedRequest 包含用于获取 HTTP 请求组件的方法,包括方法、URI 和任何标头。所有这些都需要发送到相应服务(如果有),请求才会生效。不过,许多预签名请求可以单独由 URI 表示。

预签名 POSTPUT 请求

许多可预签名的操作只需要一个 URL,并且必须作为 HTTP GET 请求发送。但是,有些操作需要正文,在某些情况下必须作为 HTTP POST 或 HTTP PUT 请求与标头一起发送。对这些请求进行预签名与对 GET 请求进行预签名相同,但是调用预签名请求更为复杂。

以下示例展示了对 Amazon S3 PutObject 请求进行预签名并将其转换为可使用所选 HTTP 客户端发送的 http::request::Request 请求的过程。

要使用 into_http_1x_request() 方法,请将 http-1x 功能添加到 Cargo.toml 文件中的 aws-sdk-s3 crate。

aws-sdk-s3 = { version = "1", features = ["http-1x"] }

源文件:

let presigned = s3.put_object() .presigned( PresigningConfig::builder() .expires_in(Duration::from_secs(60 * 5)) .build() .expect("less than one week") ) .await?; let body = "Hello AWS SDK for Rust"; let http_req = presigned.into_http_1x_request(body);

独立签署人

注意

这是一个高级使用案例。对于大多数用户来说,既不需要也不建议使用。

在一些使用案例中,需要在适用于 Rust 的 SDK 上下文之外创建签名请求。为此,您可以独立于 SDK 使用 aws-sigv4 crate。

以下示例展示了基本元素。有关更多详细信息,请参阅 crate 文档。

aws-sigv4http crate 添加到 Cargo.toml 文件中:

[dependencies] aws-sigv4 = "1" http = "1"

源文件:

use aws_smithy_runtime_api::client::identity::Identity; use aws_sigv4::http_request::{sign, SigningSettings, SigningParams, SignableRequest}; use aws_sigv4::sign::v4; use std::time::SystemTime; // Set up information and settings for the signing. // You can obtain credentials from `SdkConfig`. let identity = Credentials::new( "AKIDEXAMPLE", "wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY", None, None, "hardcoded-credentials").into(); let settings = SigningSettings::default(); let params = v4::SigningParams::builder() .identity(&identity) .region("us-east-1") .name("service") .time(SystemTime::now()) .settings(settings) .build()? .into(); // Convert the HTTP request into a signable request. let signable = SignableRequest::new( "GET", "https://some-endpoint.some-region.amazonaws.com", std::iter::empty(), SignableBody::UnsignedPayload )?; // Sign and then apply the signature to the request. let (signing_instructions, _signature) = sign(signable, &params)?.into_parts(); let mut my_req = http::Request::new("..."); signing_instructions.apply_to_request_http1x(&mut my_req);