#s3 #aws #signature #web

s3v4

使用AWS S3版本4协议签名请求和URL的库

2个版本

0.3.5 2023年6月17日
0.3.4 2022年6月5日

422身份验证

Download history 12/week @ 2024-03-09 1/week @ 2024-03-16 3/week @ 2024-03-23 50/week @ 2024-03-30 19/week @ 2024-04-06 16/week @ 2024-04-13 29/week @ 2024-04-20 14/week @ 2024-04-27 23/week @ 2024-05-04 72/week @ 2024-05-11 36/week @ 2024-05-18 58/week @ 2024-05-25 133/week @ 2024-06-01 6/week @ 2024-06-08 68/week @ 2024-06-15 28/week @ 2024-06-22

每月241 次下载

BSD-3-Clause

24KB
324

s3v4:用于签名S3请求和预签名URL的crate

参考

此crate提供了一个signature函数,可用于对S3端点的请求进行签名,以及一个pre_signed_url函数用于生成预签名URL。

这两个函数都返回由error_chain crate生成的Error,该Error可以转换为String,或通过description方法或display_chainbacktrace方法访问,如果需要完整的回溯信息。

./examples文件夹中提供了如何使用签名头部或预签名URL上传和下载数据的示例。

示例

签名请求

   let signature: s3v4::Signature = s3v4::signature(
       url,
       method,
       &access,
       &secret,
       &region,
       &"s3",
       "UNSIGNED-PAYLOAD", //payload hash, or "UNSIGNED-PAYLOAD"
   ).map_err(|err| format!("Signature error: {}", err.display_chain()))?;

使用签名数据发送请求

Hyper

   let req = Request::builder()
       .method(Method::PUT)
       .header("x-amz-content-sha256", "UNSIGNED-PAYLOAD")
       .header("x-amz-date", &signature.date_time)
       .header("authorization", &signature.auth_header)

Ureq

   let agent = AgentBuilder::new().build();
   let response = agent
       .put(&uri)
       .set("x-amz-content-sha256", "UNSIGNED-PAYLOAD")
       .set("x-amz-date", &signature.date_time)
       .set("authorization", &signature.auth_header)

生成预签名URL

    let pre_signed_url = s3v4::pre_signed_url(
        &access,
        &secret,
        expiration,
        &url,
        &method,
        &payload_hash,
        &region,
        &date_time,
        &service,
    )
    .map_err(|err| format!("{:?}", err))?;

以下代码可以用来生成预签名URL。

use url;
fn main() -> Result<(), String> {
    let url =
        url::Url::parse(&std::env::args().nth(1).expect("missing url")).expect("malformed URL");
    let access = std::env::args().nth(2).expect("missing access");
    let secret = std::env::args().nth(3).expect("missing secret");
    let method = std::env::args().nth(4).expect("missing method");
    let expiration = std::env::args()
        .nth(5)
        .expect("missing expiration (seconds)")
        .parse::<u64>()
        .expect("wrong expiration format");
    let region = std::env::args().nth(6).expect("missing region");
    let service = std::env::args().nth(7).expect("missing service");
    let date_time: chrono::DateTime<chrono::Utc> = match std::env::args().nth(8) {
        Some(d) => chrono::DateTime::parse_from_rfc3339(&d)
            .expect("Invalid date format (should be \"YYYY-MM-DDTHH:MM:SSZ)\"")
            .into(),
        None => chrono::Utc::now(),
    };
    let payload_hash = "UNSIGNED-PAYLOAD";
    let pre_signed_url = s3v4::pre_signed_url(
        &access,
        &secret,
        expiration,
        &url,
        &method,
        &payload_hash,
        &region,
        &date_time,
        &service,
    )
    .map_err(|err| format!("{:?}", err))?;
    println!("{}", pre_signed_url);
    Ok(())
}

运行方法

cargo run --example presign -- <endpoint URL> <access> <secret> <method> \
   <expiration in seconds> <region> ["YYYY-MM-DDTHH:MM:SSZ" (timestamp)]

要发送请求,请使用curl,对于

  • -IHEAD请求
  • --file-upload为PUT请求
  • 对于GET请求不使用任何选项

依赖关系

~5-6.5MB
~150K SLoC