Apache Reqsign 0.20.7 常用工具与 API 详解
Apache Reqsign 0.20.7 常用工具与 API 详解:Reqsign 以 Rust crate 形态提供、配套 cargo 命令(search/info/add/vendor/tree),逐类速查 Signer/Context/Credential 提供者/RequestSigner/Credential 核心 API 与各云服务便捷入口,含代码示例与 FAQ,全程实测。
Apache Reqsign 0.20.7 常用工具与 API 详解
目标:详解 Apache Reqsign 0.20.7 的核心 API 与配套工具使用。Reqsign 以 Rust crate(库)形态提供,没有独立的命令行签名程序,日常操作通过 cargo 工具管理依赖、通过 Rust API 完成签名。本文按类速查
Signer/Context/Credential提供者/RequestSigner/Credential等关键 API 与各云服务便捷入口,给出代码示例与 FAQ。所有示例在 Ubuntu 22.04.5 + rustc 1.99.0 环境实测。
一、环境信息
- 操作系统:Ubuntu 22.04.5 LTS
- Rust 工具链:rustc 1.99.0 / cargo 1.99.0(rustup stable)
- Reqsign 版本:0.20.7(feature:aws-v4;依赖 reqsign-aws-v4 3.3.1 / reqsign-aws-core 3.2.0 / reqsign-core 3.3.2)
- 示例工程:
/root/reqsign-demo/
二、工具概览
Reqsign 以「Rust crate + cargo 工具」形态提供,没有 reqsign 命令行可执行程序;对请求的全部签名操作都通过 Rust API 完成。配套工具是 cargo 本身:
| 工具/API 类别 | 代表命令/类 | 作用 |
|---|---|---|
| 依赖管理 | cargo search reqsign / cargo info reqsign | 查版本、license、rust-version、features |
| 依赖引入 | cargo add reqsign --features aws-v4 | 写入 Cargo.toml 依赖 |
| 依赖查看 | cargo tree | 展示传递依赖树 |
| 离线打包 | cargo vendor | 打包全部依赖源码供内网编译 |
| 构建运行 | cargo build / cargo run | 编译与运行示例 |
| 签名组装 | Signer / Context | 签名入口与基础设施 |
| 凭据获取 | StaticCredentialProvider / EnvCredentialProvider / DefaultCredentialProvider | 提供访问凭据 |
| 服务签名器 | RequestSigner / aliyun::RequestSigner / tencent::RequestSigner | 按云服务规范生成签名 |
三、前置条件
安装 Rust 工具链与 reqsign 依赖,编译运行示例工程:
source "$HOME/.cargo/env"
cd /root/reqsign-demo
cargo build
四、核心 API 详解
4.1 Signer(签名入口)
Signer::new(ctx, credential_provider, request_signer) 组装三要素后,用 sign() 对请求签名:
use reqsign::{Context, Signer};
use reqsign::aws::{RequestSigner, StaticCredentialProvider};
let ctx = Context::new();
let cred = StaticCredentialProvider::new("AKIDEXAMPLE", "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY");
let signer = Signer::new(ctx, cred, RequestSigner::new("s3", "us-east-1"));
let mut parts = http::Request::get("http://127.0.0.1:8000/my-bucket/demo.txt")
.body(())
.unwrap()
.into_parts()
.0;
signer.sign(&mut parts, None).await?; // 成功后 parts.uri / parts.headers 被改写
常用方法:
| 方法 | 说明 |
|---|---|
Signer::new(ctx, provider, signer) | 组装签名器 |
with_context(ctx) / with_credential_provider(p) / with_request_signer(s) | 链式替换组件 |
sign(&mut Parts, Option<Duration>) | 异步执行签名,成功只改 uri 与 headers |
4.2 Context(上下文基础设施)
Context 提供签名所需的文件读取、HTTP 发送、环境变量与命令执行能力:
use reqsign::default_context;
use reqsign::Context;
let ctx = default_context(); // TokioFileRead + ReqwestHttpSend + OsEnv + TokioCommandExecute
// 自定义:
let ctx = Context::new()
.with_env(reqsign::OsEnv);
| 方法 | 说明 |
|---|---|
default_context() | 默认实现组合(需 default-context feature) |
Context::new() | 空上下文,逐项注入 |
with_file_read(impl FileRead) / with_http_send(impl HttpSend) / with_env(impl Env) / with_command_execute(impl CommandExecute) | 替换对应组件 |
4.3 凭据提供者(Credential Provider)
三种常用提供者:
use reqsign::aws::{StaticCredentialProvider, EnvCredentialProvider, DefaultCredentialProvider};
// 静态凭据(演示/固定凭据)
let p1 = StaticCredentialProvider::new("AKIDEXAMPLE", "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY");
// 环境变量凭据(AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY / AWS_SESSION_TOKEN)
let p2 = EnvCredentialProvider::new();
// 默认凭据链(env → profile → sso → web_identity → process → ecs → imds,生产推荐)
let p3 = DefaultCredentialProvider::new();
| 提供者 | 说明 |
|---|---|
StaticCredentialProvider::new(ak, sk) | 固定凭据 |
EnvCredentialProvider::new() | 环境变量凭据 |
DefaultCredentialProvider::new() | 默认凭据链,自动从环境变量、~/.aws/credentials、SSO、Web Identity、ECS/IMDS 取凭据 |
DefaultCredentialProvider::new().push_front(p) | 把自定义提供者插到链首优先尝试 |
4.4 RequestSigner(服务签名器)
RequestSigner 按云服务规范计算签名(AWS SigV4),构造参数为服务名与区域:
use reqsign::aws::RequestSigner;
let signer = RequestSigner::new("s3", "us-east-1"); // S3 / 区域 us-east-1
let s3express = RequestSigner::new("s3express", "us-west-2")
.with_standard_session_token(); // S3 Express + IAM/STS 临时凭据
| 方法 | 说明 |
|---|---|
new(service, region) | 指定签名服务与区域 |
with_standard_session_token() | 会话令牌用标准 x-amz-security-token 表示(S3 Express + IAM/STS) |
4.5 Credential(凭据数据)
签名使用的凭据数据,由各提供者产出:
// Credential { access_key_id, secret_access_key, session_token: Option<String>, expires_in: Option<Timestamp> }
四个字段:access_key_id、secret_access_key(仅参与计算,Debug 输出会被脱敏)、session_token(临时会话令牌,可选)、expires_in(过期时间,可选)。签名器内部会缓存凭据并在过期前自动刷新。
4.6 各云服务便捷入口(default_signer)
开启对应 feature 后,各云服务提供一步到位的 default_signer 便捷函数(默认上下文 + 默认凭据链 + 服务签名器):
// AWS S3(feature aws-v4):服务 s3、区域 us-east-1
let signer = reqsign::aws::default_signer("s3", "us-east-1");
// 阿里云 OSS(feature aliyun):按 bucket 签名
// let signer = reqsign::aliyun::default_signer("mybucket");
// 腾讯云 COS(feature tencent)
// let signer = reqsign::tencent::default_signer();
💡 说明:
aws::default_signer实测可用(依赖 default-context feature);aliyun::default_signer(bucket)、tencent::default_signer()为源码级 API(feature 未开启时不可用),用法一致:signer.sign(&mut parts, None).await?。
4.7 配套 cargo 工具命令
依赖生命周期管理(全部实测回显):
cargo search reqsign --limit 3 # 查 crates.io:reqsign = "0.20.7"(当前最新版)
cargo info reqsign # version 0.20.7 / license Apache-2.0 / rust-version 1.86.0 / features
cargo add reqsign --features aws-v4 # Adding reqsign v0.20.7 to dependencies
cargo tree # 查看传递依赖树(reqsign v0.20.7 → reqsign-aws-v4 v3.3.1 → reqsign-core v3.3.2)
cargo vendor --locked vendor # 打包离线依赖(输出 replace-with 配置提示)
cargo remove reqsign # Removing reqsign from dependencies(卸载)
五、完整最小可运行示例
把上述 API 串成一次「签名 + 打印签名头 + 发送验证」的完整程序(对应《构建并运行示例应用指南》篇的可执行源码),核心调用如下:
use reqsign::aws::{RequestSigner, StaticCredentialProvider, EMPTY_STRING_SHA256};
use reqsign::{Context, Signer};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let cred = StaticCredentialProvider::new("AKIDEXAMPLE", "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY");
let ctx = Context::new();
let signer = Signer::new(ctx, cred, RequestSigner::new("s3", "us-east-1"));
let req = http::Request::get("http://127.0.0.1:8000/my-bucket/demo.txt")
.header("x-amz-content-sha256", EMPTY_STRING_SHA256)
.body(())
.unwrap();
let (mut parts, _) = req.into_parts();
signer.sign(&mut parts, None).await?;
println!("authorization: {}", parts.headers.get("authorization").unwrap().to_str()?);
println!("x-amz-date: {}", parts.headers.get("x-amz-date").unwrap().to_str()?);
Ok(())
}
运行实测输出(节选):
== 签名后的请求头 ==
authorization: AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20261012/us-east-1/s3/aws4_request, SignedHeaders=host;x-amz-content-sha256;x-amz-date, Signature=37962216ce11dc6ee635a8aac517e295cb23b0e6856a687141d085e31901c711
x-amz-date: 20261012T164829Z
x-amz-content-sha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
六、注意事项
⚠️ 注意:
- Reqsign 没有
reqsign命令行工具,必须通过 Rust 代码调用 crate 完成签名;cargo 只是依赖管理/构建工具。signer.sign()操作http::request::Parts:构造请求用http::Request::builder(),得到Parts后签名,再把签名头交给自己的 HTTP 客户端发送(reqwest/curl 均可)。- 各云服务模块受 feature 开关控制(aws-v4、aliyun、tencent 等),未开启的模块在代码中引用会编译失败。
- 演示密钥
AKIDEXAMPLE仅用于演示;生产凭据务必通过环境变量/配置文件/临时凭据链获取,切勿硬编码。
七、常见问题
Q1:Reqsign 有命令行工具吗?
没有独立的命令行签名程序。签名通过 Rust API 完成;依赖与构建用 cargo 工具(cargo add / cargo build / cargo run)。
Q2:引用 reqsign::aliyun 报错找不到模块?
未开启对应 feature。在 Cargo.toml 中把 aliyun(或 tencent 等)加入 features:reqsign = { version = "0.20.7", features = ["aws-v4", "aliyun"] }。
Q3:sign 返回错误(凭据为空/来源不可用)?
先确认凭据提供者能产出凭据:静态凭据两个参数非空;环境变量两个必填变量已导出;默认链在可联网且配置就绪的机器上使用。
Q4:如何把签名后的请求发给服务端?
parts 中已有签名头(authorization / x-amz-date / 等),用 reqwest::Client 重建请求:client.request(method, uri).headers(headers).body(body).send();reqwest 0.12 的 Request 没有 from_parts 构造函数,须用上述 RequestBuilder 方式。
Q5:cargo vendor 后离线编译报缺依赖?
vendor/ 生成后需按输出提示在工程 .cargo/config.toml 写入 [source.crates-io] replace-with = "vendored-sources"(详见《安装指南》篇第五节),再用 cargo build --offline 编译。
八、参考链接
- Reqsign 官方文档:
https://docs.rs/reqsign - crates.io:
https://crates.io/crates/reqsign - Cargo 手册:
https://doc.rust-lang.org/cargo/ - AWS SigV4 签名规范:
https://docs.aws.amazon.com/general/latest/gr/signature-version-4.html - 源码仓库:
https://github.com/apache/opendal-reqsign