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 }