# API签名工具 - Rust实现 ## 项目结构 根据实际项目文件结构: ```plaintext rust/ ├── Cargo.toml # Cargo配置文件 ├── Cargo.lock # 依赖锁定文件 ├── src/ │ ├── main.rs # 命令行工具入口 │ └── lib.rs # 库入口和核心实现 └── target/ # 构建输出目录 ``` ## 使用方法 ### 构建项目 ```bash cargo build --release ``` ### 运行命令行工具 ```bash cargo run --release -- [选项] ``` 或使用编译后的二进制文件: ```bash ./target/release/apisign [选项] ``` ### 命令行选项 | 选项 | 描述 | |------|------| | `-a, --algorithm` | 签名算法: md5, sha1, sha256, hmac-sha256 | | `-u, --url` | API基础URL | | `-p, --param` | 请求参数,格式为key=value,可多次使用 | | `-k, --key` | 访问密钥ID | | `-s, --secret` | 密钥 | | `-c, --channel` | 合作渠道方ID | | `-h, --help` | 显示帮助信息 | | `-m, --mode` | 操作模式: sign_url, sign_params, verify | | `-t, --timestamp` | 自定义时间戳 | | `-n, --nonce` | 自定义随机字符串 | | `--version` | 显示版本信息 | ### 常用命令示例 **基本用法** ```bash ./target/release/apisign ``` **自定义参数** ```bash ./target/release/apisign \ -u "https://api.example.com/user/info" \ -p "userId=12345" -p "action=getInfo" \ -k "YOUR_ACCESS_KEY" \ -s "YOUR_SECRET_KEY" \ -c "3" ``` **指定签名算法** ```bash ./target/release/apisign -a sha256 ``` **生成签名参数** ```bash ./target/release/apisign -m sign_params -p "userId=12345" -p "action=getData" ``` **验证签名** ```bash ./target/release/apisign -m verify -p "userId=12345" -p "action=getData" -p "AccessKeyId=test-key" -p "channelId=test-channel" -p "timestamp=1621234567890" -p "nonce=abc123" -p "sign=calculated-signature-here" ``` **帮助信息** ```bash ./target/release/apisign --help ``` ### API接口测试实例 使用真实API接口进行测试: ```bash # 未签名的API调用测试 - 返回错误 curl "https://api-v1.sound-force.com:8443/p/album/single/media-url?channelId=3&singleId=381980" # 返回: {"code":400,"data":null,"msg":"Missing AccessKeyId","success":false} # 生成访问https://api-v1.sound-force.com:8443/p/album/single/media-url的签名URL ./target/release/apisign \ -a md5 \ -u "https://api-v1.sound-force.com:8443/p/album/single/media-url" \ -p "singleId=381980" \ -k "YOUR_ACCESS_KEY" \ -s "YOUR_SECRET_KEY" \ -c "3" # 使用curl测试API接口 signed_url=$(./target/release/apisign \ -a md5 \ -u "https://api-v1.sound-force.com:8443/p/album/single/media-url" \ -p "singleId=381980" \ -k "YOUR_ACCESS_KEY" \ -s "YOUR_SECRET_KEY" \ -c "3" | grep -A 1 "签名后的URL:" | tail -n 1) curl -v "$signed_url" ``` 请注意: - 替换`YOUR_ACCESS_KEY`为实际的访问密钥ID - 替换`YOUR_SECRET_KEY`为实际的密钥 - 示例使用的渠道ID为`3`,请根据实际情况调整 使用有效的密钥和签名后,API接口将返回成功响应(状态码200)并提供媒体URL数据。 ### Rust Reqwest客户端测试示例 ```rust use std::process::Command; use reqwest; use std::io::{self, Write}; #[tokio::main] async fn main() -> Result<(), Box> { // 获取签名URL let output = Command::new("./target/release/apisign") .args(&[ "-a", "md5", "-u", "https://api-v1.sound-force.com:8443/p/album/single/media-url", "-p", "singleId=381980", "-k", "YOUR_ACCESS_KEY", "-s", "YOUR_SECRET_KEY", "-c", "3" ]) .output()?; let output_str = String::from_utf8(output.stdout)?; let lines: Vec<&str> = output_str.lines().collect(); // 提取URL let mut signed_url = ""; for (i, line) in lines.iter().enumerate() { if line.contains("签名后的URL:") && i + 1 < lines.len() { signed_url = lines[i + 1].trim(); break; } } println!("签名生成的URL: {}", signed_url); if !signed_url.is_empty() { // 发送请求 let client = reqwest::Client::new(); let response = client.get(signed_url).send().await?; println!("状态码: {}", response.status()); let body = response.text().await?; println!("响应内容: {}", body); } else { println!("无法从输出中获取签名URL"); } Ok(()) } ``` ### 代码集成 ```rust use apisign::{ApiSigner, SignOptions, SignatureAlgorithm}; use std::collections::HashMap; fn main() { // 创建签名选项 let options = SignOptions::new() .with_algorithm(SignatureAlgorithm::Md5); // 创建签名工具 let signer = ApiSigner::new(options); // 准备请求参数 let mut params = HashMap::new(); params.insert("singleId".to_string(), "381980".to_string()); // 执行签名 let signed_params = signer.sign_request( ¶ms, "YOUR_ACCESS_KEY", "YOUR_SECRET_KEY", "3" ).unwrap(); // 或签名URL let signed_url = signer.sign_url( "https://api-v1.sound-force.com:8443/p/album/single/media-url", ¶ms, "YOUR_ACCESS_KEY", "YOUR_SECRET_KEY", "3" ).unwrap(); println!("{}", signed_url); } ``` ### 环境变量 该工具支持从`.env`文件加载以下配置: - `ACCESS_KEY_ID`: 访问密钥ID - `SECRET_KEY`: 密钥 - `CHANNEL_ID`: 渠道ID - `SIGN_ALGORITHM`: 签名算法 - `API_BASE_URL`: API基础URL