Files
lone-services/services/chore/internal/logic/policyLogic.go
T
2026-08-24 15:57:08 +08:00

143 lines
4.2 KiB
Go
Raw 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.
package logic
import (
"context"
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"encoding/hex"
"encoding/json"
"fmt"
"hash"
"io"
"time"
"lone-services/pkg/utils"
chore "lone-services/rpc/chore/pb"
"lone-services/services/chore/internal/svc"
"github.com/aliyun/credentials-go/credentials"
"github.com/zeromicro/go-zero/core/logx"
)
type PolicyLogic struct {
ctx context.Context
svcCtx *svc.ServiceContext
logx.Logger
}
type PolicyToken struct {
Policy string `json:"policy"`
SecurityToken string `json:"security_token"`
SignatureVersion string `json:"x_oss_signature_version"`
Credential string `json:"x_oss_credential"`
Date string `json:"x_oss_date"`
Signature string `json:"signature"`
Host string `json:"host"`
Dir string `json:"dir"`
}
func NewPolicyLogic(ctx context.Context, svcCtx *svc.ServiceContext) *PolicyLogic {
return &PolicyLogic{
ctx: ctx,
svcCtx: svcCtx,
Logger: logx.WithContext(ctx),
}
}
var (
region string
bucketName string
product = "oss"
)
func (l *PolicyLogic) Policy(in *chore.PolicyReq) (*chore.Response, error) {
// 设置bucket所处地域
region = utils.GetConfigString("oss.region")
// 替换为您的bucket名称
bucketName = utils.GetConfigString("oss.bucketName")
// 设置 OSS 上传地址
// lone-images.oss-accelerate.aliyuncs.com
host := fmt.Sprintf("https://%s.oss-%s.aliyuncs.com", bucketName, region)
// 设置上传目录
dir := utils.GetConfigString("oss.dir")
config := new(credentials.Config).
SetType("ram_role_arn").
SetAccessKeyId(utils.GetConfigString("oss.accessKeyId")).
SetAccessKeySecret(utils.GetConfigString("oss.accessKeySecret")).
SetRoleArn(utils.GetConfigString("oss.roleArn")).
SetRoleSessionName(utils.GetConfigString("oss.roleSessionName")).
SetPolicy("").
SetRoleSessionExpiration(3600)
// 根据配置创建凭证提供器
provider, err := credentials.NewCredential(config)
if err != nil {
l.Errorf("NewCredential fail, err:%v", err)
}
// 从凭证提供器获取凭证
cred, err := provider.GetCredential()
if err != nil {
l.Errorf("GetCredential fail, err:%v", err)
}
// 构建policy
utcTime := time.Now().UTC()
date := utcTime.Format("20060102")
expiration := utcTime.Add(1 * time.Hour)
policyMap := map[string]any{
"expiration": expiration.Format("2006-01-02T15:04:05.000Z"),
"conditions": []any{
map[string]string{"bucket": bucketName},
map[string]string{"x-oss-signature-version": "OSS4-HMAC-SHA256"},
map[string]string{"x-oss-credential": fmt.Sprintf("%v/%v/%v/%v/aliyun_v4_request", *cred.AccessKeyId, date, region, product)},
map[string]string{"x-oss-date": utcTime.Format("20060102T150405Z")},
map[string]string{"x-oss-security-token": *cred.SecurityToken},
},
}
// 将policy转换为 JSON 格式
policy, err := json.Marshal(policyMap)
if err != nil {
l.Errorf("json.Marshal fail, err:%v", err)
}
// 构造待签名字符串(StringToSign
stringToSign := base64.StdEncoding.EncodeToString([]byte(policy))
hmacHash := func() hash.Hash { return sha256.New() }
// 构建signing key
signingKey := "aliyun_v4" + *cred.AccessKeySecret
h1 := hmac.New(hmacHash, []byte(signingKey))
io.WriteString(h1, date)
h1Key := h1.Sum(nil)
h2 := hmac.New(hmacHash, h1Key)
io.WriteString(h2, region)
h2Key := h2.Sum(nil)
h3 := hmac.New(hmacHash, h2Key)
io.WriteString(h3, product)
h3Key := h3.Sum(nil)
h4 := hmac.New(hmacHash, h3Key)
io.WriteString(h4, "aliyun_v4_request")
h4Key := h4.Sum(nil)
// 生成签名
h := hmac.New(hmacHash, h4Key)
io.WriteString(h, stringToSign)
signature := hex.EncodeToString(h.Sum(nil))
// 构建返回给前端的表单
policyToken := PolicyToken{
Policy: stringToSign,
SecurityToken: *cred.SecurityToken,
SignatureVersion: "OSS4-HMAC-SHA256",
Credential: fmt.Sprintf("%v/%v/%v/%v/aliyun_v4_request", *cred.AccessKeyId, date, region, product),
Date: utcTime.UTC().Format("20060102T150405Z"),
Signature: signature,
Host: host, // 返回 OSS 上传地址
Dir: dir, // 返回上传目录
}
response, err := json.Marshal(policyToken)
if err != nil {
fmt.Println("json err:", err)
}
return &chore.Response{
Code: 0,
Data: string(response),
}, nil
}