✨ 添加API签名工具的初始实现,包括模块定义、主程序、签名库和文档。
This commit is contained in:
237
go/README.md
Normal file
237
go/README.md
Normal file
@@ -0,0 +1,237 @@
|
||||
# API签名工具 - Go实现
|
||||
|
||||
## 项目结构
|
||||
|
||||
根据实际项目文件结构:
|
||||
|
||||
```plaintext
|
||||
go/
|
||||
├── main.go # 主程序入口
|
||||
├── apisign/ # 签名库核心代码目录
|
||||
│ └── signer.go # 签名工具实现
|
||||
├── go.mod # Go模块定义
|
||||
└── go.sum # 依赖版本锁定
|
||||
```
|
||||
|
||||
## 使用方法
|
||||
|
||||
### 构建项目
|
||||
|
||||
```bash
|
||||
go build -o apisign
|
||||
```
|
||||
|
||||
### 运行命令行工具
|
||||
|
||||
```bash
|
||||
./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` | 自定义时间戳 |
|
||||
|
||||
### 常用命令示例
|
||||
|
||||
**基本用法**
|
||||
|
||||
```bash
|
||||
./apisign
|
||||
```
|
||||
|
||||
**自定义参数**
|
||||
|
||||
```bash
|
||||
./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
|
||||
./apisign -a sha256
|
||||
```
|
||||
|
||||
**生成签名参数**
|
||||
|
||||
```bash
|
||||
./apisign -m params -p "userId=12345" -p "action=getData"
|
||||
```
|
||||
|
||||
**验证签名**
|
||||
|
||||
```bash
|
||||
./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
|
||||
./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
|
||||
./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客户端测试示例
|
||||
|
||||
```go
|
||||
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)
|
||||
}
|
||||
```
|
||||
|
||||
### 代码集成
|
||||
|
||||
```go
|
||||
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
|
||||
309
go/apisign/signer.go
Normal file
309
go/apisign/signer.go
Normal file
@@ -0,0 +1,309 @@
|
||||
// Package apisign 提供API签名计算与验证功能
|
||||
package apisign
|
||||
|
||||
import (
|
||||
"crypto/hmac"
|
||||
"crypto/md5"
|
||||
"crypto/sha1"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// SignatureAlgorithm 签名算法类型
|
||||
type SignatureAlgorithm int
|
||||
|
||||
const (
|
||||
// MD5算法(默认、最快)
|
||||
MD5 SignatureAlgorithm = iota
|
||||
// SHA1算法
|
||||
SHA1
|
||||
// SHA256算法
|
||||
SHA256
|
||||
// HMACSHA256算法(最安全)
|
||||
HMACSHA256
|
||||
)
|
||||
|
||||
// String 返回算法的字符串表示
|
||||
func (a SignatureAlgorithm) String() string {
|
||||
switch a {
|
||||
case MD5:
|
||||
return "MD5"
|
||||
case SHA1:
|
||||
return "SHA1"
|
||||
case SHA256:
|
||||
return "SHA256"
|
||||
case HMACSHA256:
|
||||
return "HMAC-SHA256"
|
||||
default:
|
||||
return "UNKNOWN"
|
||||
}
|
||||
}
|
||||
|
||||
// ParseAlgorithm 从字符串解析算法类型
|
||||
func ParseAlgorithm(s string) (SignatureAlgorithm, error) {
|
||||
switch strings.ToUpper(s) {
|
||||
case "MD5":
|
||||
return MD5, nil
|
||||
case "SHA1":
|
||||
return SHA1, nil
|
||||
case "SHA256":
|
||||
return SHA256, nil
|
||||
case "HMAC_SHA256", "HMACSHA256", "HMAC-SHA256":
|
||||
return HMACSHA256, nil
|
||||
default:
|
||||
return MD5, fmt.Errorf("unknown algorithm: %s", s)
|
||||
}
|
||||
}
|
||||
|
||||
// SignOptions 签名选项
|
||||
type SignOptions struct {
|
||||
// 签名算法
|
||||
Algorithm SignatureAlgorithm
|
||||
// AccessKeyId参数名
|
||||
KeyName string
|
||||
// ChannelId参数名
|
||||
ChannelIdName string
|
||||
// 时间戳参数名
|
||||
TimestampName string
|
||||
// 随机字符串参数名
|
||||
NonceName string
|
||||
// 签名参数名
|
||||
SignatureName string
|
||||
}
|
||||
|
||||
// NewDefaultSignOptions 创建默认签名选项
|
||||
func NewDefaultSignOptions() *SignOptions {
|
||||
return &SignOptions{
|
||||
Algorithm: MD5,
|
||||
KeyName: "AccessKeyId",
|
||||
ChannelIdName: "channelId",
|
||||
TimestampName: "timestamp",
|
||||
NonceName: "nonce",
|
||||
SignatureName: "signature",
|
||||
}
|
||||
}
|
||||
|
||||
// APISigner API签名工具
|
||||
type APISigner struct {
|
||||
options *SignOptions
|
||||
}
|
||||
|
||||
// NewAPISigner 创建API签名工具
|
||||
//
|
||||
// 参数:
|
||||
// - options: 签名选项,如为nil则使用默认选项
|
||||
//
|
||||
// 返回:
|
||||
// - 签名工具实例
|
||||
func NewAPISigner(options *SignOptions) *APISigner {
|
||||
if options == nil {
|
||||
options = NewDefaultSignOptions()
|
||||
}
|
||||
return &APISigner{options: options}
|
||||
}
|
||||
|
||||
// GenerateNonce 生成随机字符串
|
||||
//
|
||||
// 返回:
|
||||
// - 一个基于当前时间的随机字符串
|
||||
func (s *APISigner) GenerateNonce() string {
|
||||
return fmt.Sprintf("%d%d", time.Now().UnixNano(), time.Now().Unix()%1000)
|
||||
}
|
||||
|
||||
// GetTimestamp 获取当前时间戳(毫秒)
|
||||
//
|
||||
// 返回:
|
||||
// - 当前的Unix时间戳(毫秒)
|
||||
func (s *APISigner) GetTimestamp() int64 {
|
||||
return time.Now().UnixMilli()
|
||||
}
|
||||
|
||||
// SignRequest 对请求进行签名
|
||||
//
|
||||
// 参数:
|
||||
// - params: 请求参数
|
||||
// - accessKeyId: 访问密钥ID
|
||||
// - secretKey: 密钥
|
||||
// - channelId: 渠道ID,如果为空则使用params中已有的channelId
|
||||
//
|
||||
// 返回:
|
||||
// - 添加了签名的完整参数
|
||||
func (s *APISigner) SignRequest(params map[string]string, accessKeyId, secretKey string, channelId ...string) map[string]string {
|
||||
signParams := make(map[string]string)
|
||||
for k, v := range params {
|
||||
signParams[k] = v
|
||||
}
|
||||
|
||||
timestamp := s.GetTimestamp()
|
||||
signParams[s.options.KeyName] = accessKeyId
|
||||
|
||||
if len(channelId) > 0 && channelId[0] != "" {
|
||||
signParams[s.options.ChannelIdName] = channelId[0]
|
||||
}
|
||||
|
||||
signParams[s.options.TimestampName] = strconv.FormatInt(timestamp, 10)
|
||||
signParams[s.options.NonceName] = s.GenerateNonce()
|
||||
|
||||
signature := s.CalculateSignature(signParams, secretKey)
|
||||
|
||||
signParams[s.options.SignatureName] = signature
|
||||
|
||||
return signParams
|
||||
}
|
||||
|
||||
// SignURL 对URL进行签名
|
||||
//
|
||||
// 参数:
|
||||
// - baseURL: 基础URL地址
|
||||
// - params: 请求参数
|
||||
// - accessKeyId: 访问密钥ID
|
||||
// - secretKey: 密钥
|
||||
// - channelId: 渠道ID,如果为空则使用params中已有的channelId
|
||||
//
|
||||
// 返回:
|
||||
// - 添加了签名的完整URL
|
||||
func (s *APISigner) SignURL(baseURL string, params map[string]string, accessKeyId, secretKey string, channelId ...string) string {
|
||||
signedParams := s.SignRequest(params, accessKeyId, secretKey, channelId...)
|
||||
|
||||
values := url.Values{}
|
||||
for k, v := range signedParams {
|
||||
values.Add(k, v)
|
||||
}
|
||||
|
||||
if strings.Contains(baseURL, "?") {
|
||||
return baseURL + "&" + values.Encode()
|
||||
}
|
||||
|
||||
return baseURL + "?" + values.Encode()
|
||||
}
|
||||
|
||||
// CalculateSignature 计算签名
|
||||
//
|
||||
// 参数:
|
||||
// - params: 请求参数
|
||||
// - secretKey: 密钥
|
||||
//
|
||||
// 返回:
|
||||
// - 签名字符串
|
||||
func (s *APISigner) CalculateSignature(params map[string]string, secretKey string) string {
|
||||
signingString := s.CreateSigningString(params)
|
||||
|
||||
signingString = signingString + "&key=" + secretKey
|
||||
|
||||
switch s.options.Algorithm {
|
||||
case SHA1:
|
||||
hasher := sha1.New()
|
||||
hasher.Write([]byte(signingString))
|
||||
return hex.EncodeToString(hasher.Sum(nil))
|
||||
case SHA256:
|
||||
hasher := sha256.New()
|
||||
hasher.Write([]byte(signingString))
|
||||
return hex.EncodeToString(hasher.Sum(nil))
|
||||
case HMACSHA256:
|
||||
hasher := hmac.New(sha256.New, []byte(secretKey))
|
||||
hasher.Write([]byte(signingString))
|
||||
return hex.EncodeToString(hasher.Sum(nil))
|
||||
default:
|
||||
hasher := md5.New()
|
||||
hasher.Write([]byte(signingString))
|
||||
return hex.EncodeToString(hasher.Sum(nil))
|
||||
}
|
||||
}
|
||||
|
||||
// CreateSigningString 创建用于签名的规范化字符串
|
||||
//
|
||||
// 参数:
|
||||
// - params: 请求参数
|
||||
//
|
||||
// 返回:
|
||||
// - 按键名排序并拼接的字符串
|
||||
func (s *APISigner) CreateSigningString(params map[string]string) string {
|
||||
sortedParams := make(map[string]string)
|
||||
for k, v := range params {
|
||||
if k != s.options.SignatureName {
|
||||
sortedParams[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
keys := make([]string, 0, len(sortedParams))
|
||||
for k := range sortedParams {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
|
||||
parts := make([]string, 0, len(keys))
|
||||
for _, k := range keys {
|
||||
v := sortedParams[k]
|
||||
if needsURLEncode(v) {
|
||||
v = url.QueryEscape(v)
|
||||
}
|
||||
parts = append(parts, k+"="+v)
|
||||
}
|
||||
|
||||
return strings.Join(parts, "&")
|
||||
}
|
||||
|
||||
// needsURLEncode 判断是否需要对字符串进行URL编码
|
||||
func needsURLEncode(s string) bool {
|
||||
for _, c := range s {
|
||||
if !((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9')) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// VerifySignature 验证签名
|
||||
//
|
||||
// 参数:
|
||||
// - params: 所有请求参数,包括签名
|
||||
// - secretKey: 密钥
|
||||
// - maxAgeMs: 允许的最大时间差(毫秒)
|
||||
//
|
||||
// 返回:
|
||||
// - 验证结果和错误信息
|
||||
func (s *APISigner) VerifySignature(params map[string]string, secretKey string, maxAgeMs int64) (bool, error) {
|
||||
_, ok := params[s.options.KeyName]
|
||||
if !ok {
|
||||
return false, fmt.Errorf("missing %s", s.options.KeyName)
|
||||
}
|
||||
|
||||
_, ok = params[s.options.ChannelIdName]
|
||||
if !ok {
|
||||
return false, fmt.Errorf("missing %s", s.options.ChannelIdName)
|
||||
}
|
||||
|
||||
timestampStr, ok := params[s.options.TimestampName]
|
||||
if !ok {
|
||||
return false, fmt.Errorf("missing %s", s.options.TimestampName)
|
||||
}
|
||||
|
||||
timestamp, err := strconv.ParseInt(timestampStr, 10, 64)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("invalid timestamp: %v", err)
|
||||
}
|
||||
|
||||
now := time.Now().UnixMilli()
|
||||
if now-timestamp > maxAgeMs || timestamp-now > maxAgeMs {
|
||||
return false, fmt.Errorf("timestamp expired")
|
||||
}
|
||||
|
||||
_, ok = params[s.options.NonceName]
|
||||
if !ok {
|
||||
return false, fmt.Errorf("missing %s", s.options.NonceName)
|
||||
}
|
||||
|
||||
providedSignature, ok := params[s.options.SignatureName]
|
||||
if !ok {
|
||||
return false, fmt.Errorf("missing %s", s.options.SignatureName)
|
||||
}
|
||||
|
||||
expectedSignature := s.CalculateSignature(params, secretKey)
|
||||
return expectedSignature == providedSignature, nil
|
||||
}
|
||||
139
go/main.go
Normal file
139
go/main.go
Normal file
@@ -0,0 +1,139 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"sound-force/sign-doc/go/apisign"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var accessKeyId string
|
||||
var secretKey string
|
||||
var apiBaseURL string
|
||||
var algorithmStr string
|
||||
var params []string
|
||||
|
||||
flag.StringVar(&accessKeyId, "k", os.Getenv("ACCESS_KEY_ID"), "访问密钥ID")
|
||||
flag.StringVar(&secretKey, "s", os.Getenv("SECRET_KEY"), "密钥")
|
||||
flag.StringVar(&apiBaseURL, "u", os.Getenv("API_BASE_URL"), "API基础URL")
|
||||
flag.StringVar(&algorithmStr, "a", os.Getenv("SIGN_ALGORITHM"), "签名算法")
|
||||
flag.Func("p", "请求参数 (格式: key=value)", func(s string) error {
|
||||
params = append(params, s)
|
||||
return nil
|
||||
})
|
||||
flag.Parse()
|
||||
|
||||
if accessKeyId == "" {
|
||||
accessKeyId = "test-access-key-id"
|
||||
}
|
||||
if secretKey == "" {
|
||||
secretKey = "test-secret-key"
|
||||
}
|
||||
if apiBaseURL == "" {
|
||||
apiBaseURL = "https://api.example.com/v1"
|
||||
}
|
||||
if algorithmStr == "" {
|
||||
algorithmStr = "MD5"
|
||||
}
|
||||
|
||||
algorithm, err := apisign.ParseAlgorithm(algorithmStr)
|
||||
if err != nil {
|
||||
fmt.Printf("Warning: %v, using MD5 as default\n", err)
|
||||
algorithm = apisign.MD5
|
||||
}
|
||||
|
||||
options := apisign.NewDefaultSignOptions()
|
||||
options.Algorithm = algorithm
|
||||
// 将签名参数名从默认的"signature"改为"sign"
|
||||
options.SignatureName = "sign"
|
||||
|
||||
signer := apisign.NewAPISigner(options)
|
||||
|
||||
requestParams := make(map[string]string)
|
||||
if len(params) > 0 {
|
||||
for _, p := range params {
|
||||
parts := strings.SplitN(p, "=", 2)
|
||||
if len(parts) == 2 {
|
||||
requestParams[parts[0]] = parts[1]
|
||||
}
|
||||
}
|
||||
} else {
|
||||
requestParams = map[string]string{
|
||||
"userId": "12345",
|
||||
"action": "getData",
|
||||
"data": "测试数据",
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println("===================== API签名示例 =====================")
|
||||
fmt.Printf("AccessKeyId: %s\n", accessKeyId)
|
||||
fmt.Printf("SecretKey: %s\n", secretKey)
|
||||
fmt.Printf("签名算法: %s\n", algorithm.String())
|
||||
fmt.Printf("基础URL: %s\n", apiBaseURL)
|
||||
fmt.Println("请求参数:", requestParams)
|
||||
|
||||
channelId := getEnv("CHANNEL_ID", "test-channel-id")
|
||||
if val, ok := requestParams["channelId"]; ok {
|
||||
channelId = val
|
||||
}
|
||||
|
||||
signedParams := signer.SignRequest(requestParams, accessKeyId, secretKey, channelId)
|
||||
fmt.Println("\n签名后的参数:")
|
||||
for k, v := range signedParams {
|
||||
fmt.Printf(" %s: %s\n", k, v)
|
||||
}
|
||||
|
||||
signedURL := signer.SignURL(apiBaseURL, requestParams, accessKeyId, secretKey, channelId)
|
||||
fmt.Println("\n签名后的URL:")
|
||||
fmt.Println(signedURL)
|
||||
|
||||
valid, err := signer.VerifySignature(signedParams, secretKey, 300000)
|
||||
fmt.Println("\n签名验证结果:")
|
||||
if err != nil {
|
||||
fmt.Printf(" 验证失败: %v\n", err)
|
||||
} else if valid {
|
||||
fmt.Println(" 验证成功")
|
||||
} else {
|
||||
fmt.Println(" 验证失败: 签名不匹配")
|
||||
}
|
||||
|
||||
fmt.Println("\n不同算法的签名结果:")
|
||||
demonstrateAlgorithms(requestParams, accessKeyId, secretKey)
|
||||
}
|
||||
|
||||
// getEnv 获取环境变量,如果不存在则返回默认值
|
||||
func getEnv(key, defaultValue string) string {
|
||||
value := os.Getenv(key)
|
||||
if value == "" {
|
||||
return defaultValue
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
// demonstrateAlgorithms 演示不同算法的签名结果
|
||||
func demonstrateAlgorithms(params map[string]string, accessKeyId, secretKey string) {
|
||||
algorithms := []apisign.SignatureAlgorithm{
|
||||
apisign.MD5,
|
||||
apisign.SHA1,
|
||||
apisign.SHA256,
|
||||
apisign.HMACSHA256,
|
||||
}
|
||||
|
||||
keys := make([]string, 0, len(params))
|
||||
for k := range params {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
strings.Join(keys, "&")
|
||||
|
||||
for _, alg := range algorithms {
|
||||
options := apisign.NewDefaultSignOptions()
|
||||
options.Algorithm = alg
|
||||
options.SignatureName = "sign"
|
||||
signer := apisign.NewAPISigner(options)
|
||||
|
||||
signature := signer.CalculateSignature(params, secretKey)
|
||||
fmt.Printf(" %s: %s\n", alg.String(), signature)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user