Files
sign-doc/rust/README.md

232 lines
5.5 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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<dyn std::error::Error>> {
// 获取签名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(
&params,
"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",
&params,
"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