143 lines
4.2 KiB
Go
143 lines
4.2 KiB
Go
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
|
||
}
|