Files

API签名工具 - Go实现

项目结构

根据实际项目文件结构:

go/
├── main.go                 # 主程序入口
├── apisign/                # 签名库核心代码目录
│   └── signer.go           # 签名工具实现
├── go.mod                  # Go模块定义
└── go.sum                  # 依赖版本锁定

使用方法

构建项目

go build -o apisign

运行命令行工具

./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 操作模式: url, params, verify
-n, --nonce 自定义随机字符串
-t, --timestamp 自定义时间戳

常用命令示例

基本用法

./apisign

自定义参数

./apisign \
  -u "https://api.example.com/user/info" \
  -p "userId=12345" -p "action=getInfo" \
  -k "YOUR_ACCESS_KEY" \
  -s "YOUR_SECRET_KEY" \
  -c "3"

指定签名算法

./apisign -a sha256

生成签名参数

./apisign -m params -p "userId=12345" -p "action=getData"

验证签名

./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"

帮助信息

./apisign --help

API接口测试实例

使用真实API接口进行测试

# 未签名的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
./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=$(./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数据。

Go HTTP客户端测试示例

package main

import (
    "fmt"
    "io/ioutil"
    "net/http"
    "os/exec"
    "strings"
)

func main() {
    // 获取签名URL
    cmd := exec.Command("./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")
    output, err := cmd.CombinedOutput()
    if err != nil {
        panic(err)
    }
    
    // 从输出中提取URL
    lines := strings.Split(string(output), "\n")
    var url string
    for i, line := range lines {
        if strings.Contains(line, "签名后的URL:") && i+1 < len(lines) {
            url = strings.TrimSpace(lines[i+1])
            break
        }
    }
    
    if url == "" {
        panic("无法从输出中获取签名URL")
    }
    
    // 发送请求
    resp, err := http.Get(url)
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()
    
    body, _ := ioutil.ReadAll(resp.Body)
    fmt.Printf("状态码: %d\n", resp.StatusCode)
    fmt.Printf("响应内容: %s\n", body)
}

代码集成

package main

import (
    "fmt"
    "github.com/soundforce/apisign"
)

func main() {
    // 创建签名选项
    options := apisign.NewOptions().
        WithAlgorithm(apisign.MD5)
    
    // 创建签名工具
    signer := apisign.NewSigner(options)
    
    // 准备请求参数
    params := map[string]string{
        "singleId": "381980",
    }
    
    // 执行签名
    signedParams, err := signer.SignRequest(
        params, 
        "YOUR_ACCESS_KEY", 
        "YOUR_SECRET_KEY", 
        "3",
    )
    if err != nil {
        panic(err)
    }
    
    // 或签名URL
    signedURL, err := signer.SignURL(
        "https://api-v1.sound-force.com:8443/p/album/single/media-url",
        params,
        "YOUR_ACCESS_KEY", 
        "YOUR_SECRET_KEY", 
        "3",
    )
    if err != nil {
        panic(err)
    }
    
    fmt.Println(signedURL)
}

环境变量

该工具支持从.env文件加载以下配置:

  • ACCESS_KEY_ID: 访问密钥ID
  • SECRET_KEY: 密钥
  • CHANNEL_ID: 渠道ID
  • SIGN_ALGORITHM: 签名算法
  • API_BASE_URL: API基础URL