feat: chore test
This commit is contained in:
@@ -2,21 +2,16 @@ package logic
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/hmac"
|
||||
"crypto/sha256"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"hash"
|
||||
"io"
|
||||
"time"
|
||||
"strings"
|
||||
|
||||
"lone-services/pkg/utils"
|
||||
chore "lone-services/rpc/chore/pb"
|
||||
"lone-services/services/chore/internal/svc"
|
||||
|
||||
"github.com/aliyun/credentials-go/credentials"
|
||||
openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client"
|
||||
sts20150401 "github.com/alibabacloud-go/sts-20150401/v2/client"
|
||||
util "github.com/alibabacloud-go/tea-utils/v2/service"
|
||||
"github.com/alibabacloud-go/tea/tea"
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
@@ -26,15 +21,17 @@ type PolicyLogic struct {
|
||||
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"`
|
||||
// StsToken 对齐阿里云 STS 返回字段,并附带前端上传所需信息
|
||||
type StsToken struct {
|
||||
AccessKeyId string `json:"AccessKeyId"`
|
||||
AccessKeySecret string `json:"AccessKeySecret"`
|
||||
SecurityToken string `json:"SecurityToken"`
|
||||
Expiration string `json:"Expiration"`
|
||||
Bucket string `json:"bucket"`
|
||||
Region string `json:"region"`
|
||||
Endpoint string `json:"endpoint"`
|
||||
Host string `json:"host"`
|
||||
Dir string `json:"dir"`
|
||||
}
|
||||
|
||||
func NewPolicyLogic(ctx context.Context, svcCtx *svc.ServiceContext) *PolicyLogic {
|
||||
@@ -45,98 +42,93 @@ func NewPolicyLogic(ctx context.Context, svcCtx *svc.ServiceContext) *PolicyLogi
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
// 设置上传目录
|
||||
accessKeyId := utils.GetConfigString("oss.accessKeyId")
|
||||
accessKeySecret := utils.GetConfigString("oss.accessKeySecret")
|
||||
roleArn := utils.GetConfigString("oss.roleArn")
|
||||
roleSessionName := utils.GetConfigString("oss.roleSessionName")
|
||||
stsEndpoint := utils.GetConfigString("oss.stsEndpoint")
|
||||
region := utils.GetConfigString("oss.region")
|
||||
bucket := utils.GetConfigString("oss.bucketName")
|
||||
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)
|
||||
endpoint := utils.GetConfigString("oss.endpoint")
|
||||
host := utils.GetConfigString("oss.host")
|
||||
|
||||
// 根据配置创建凭证提供器
|
||||
provider, err := credentials.NewCredential(config)
|
||||
if accessKeyId == utils.StringEmpty || accessKeySecret == utils.StringEmpty || roleArn == utils.StringEmpty {
|
||||
l.Errorf("oss config missing: accessKeyId/accessKeySecret/roleArn")
|
||||
return failResponse(utils.Fail), nil
|
||||
}
|
||||
if roleSessionName == utils.StringEmpty {
|
||||
roleSessionName = "chore-oss-upload"
|
||||
}
|
||||
if stsEndpoint == utils.StringEmpty {
|
||||
stsEndpoint = "sts.cn-hangzhou.aliyuncs.com"
|
||||
}
|
||||
if bucket == utils.StringEmpty {
|
||||
bucket = "lone-images"
|
||||
}
|
||||
if region == utils.StringEmpty {
|
||||
region = "oss-cn-hangzhou"
|
||||
}
|
||||
if endpoint == utils.StringEmpty {
|
||||
endpoint = "https://lone-images.oss-accelerate.aliyuncs.com"
|
||||
}
|
||||
if host == utils.StringEmpty {
|
||||
host = "https://images.ailuowan.com"
|
||||
}
|
||||
if !strings.HasPrefix(endpoint, "http") {
|
||||
endpoint = "https://" + endpoint
|
||||
}
|
||||
if !strings.HasPrefix(host, "http") {
|
||||
host = "https://" + host
|
||||
}
|
||||
|
||||
expire := int64(utils.GetConfigInt("oss.expireSeconds"))
|
||||
if expire < 1 {
|
||||
expire = 3600
|
||||
}
|
||||
|
||||
client, err := createStsClient(accessKeyId, accessKeySecret, stsEndpoint)
|
||||
if err != nil {
|
||||
l.Errorf("NewCredential fail, err:%v", err)
|
||||
l.Errorf("create STS client: %v", err)
|
||||
return failResponse(utils.Fail), nil
|
||||
}
|
||||
// 从凭证提供器获取凭证
|
||||
cred, err := provider.GetCredential()
|
||||
|
||||
assumeRoleRequest := &sts20150401.AssumeRoleRequest{
|
||||
DurationSeconds: tea.Int64(expire),
|
||||
RoleArn: tea.String(roleArn),
|
||||
RoleSessionName: tea.String(roleSessionName),
|
||||
}
|
||||
resp, err := client.AssumeRoleWithOptions(assumeRoleRequest, &util.RuntimeOptions{})
|
||||
if err != nil {
|
||||
l.Errorf("GetCredential fail, err:%v", err)
|
||||
l.Errorf("AssumeRole: %v", err)
|
||||
return failResponse(utils.Fail), nil
|
||||
}
|
||||
// 构建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},
|
||||
},
|
||||
if resp == nil || resp.Body == nil || resp.Body.Credentials == nil {
|
||||
l.Errorf("AssumeRole empty credentials")
|
||||
return failResponse(utils.Fail), nil
|
||||
}
|
||||
// 将policy转换为 JSON 格式
|
||||
policy, err := json.Marshal(policyMap)
|
||||
if err != nil {
|
||||
l.Errorf("json.Marshal fail, err:%v", err)
|
||||
|
||||
cred := resp.Body.Credentials
|
||||
token := StsToken{
|
||||
AccessKeyId: tea.StringValue(cred.AccessKeyId),
|
||||
AccessKeySecret: tea.StringValue(cred.AccessKeySecret),
|
||||
SecurityToken: tea.StringValue(cred.SecurityToken),
|
||||
Expiration: tea.StringValue(cred.Expiration),
|
||||
Bucket: bucket,
|
||||
Region: region,
|
||||
Endpoint: endpoint,
|
||||
Host: host,
|
||||
Dir: dir,
|
||||
}
|
||||
// 构造待签名字符串(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
|
||||
return okResponse(token), nil
|
||||
}
|
||||
|
||||
func createStsClient(accessKeyId, accessKeySecret, endpoint string) (*sts20150401.Client, error) {
|
||||
config := &openapi.Config{
|
||||
AccessKeyId: tea.String(accessKeyId),
|
||||
AccessKeySecret: tea.String(accessKeySecret),
|
||||
Endpoint: tea.String(endpoint),
|
||||
}
|
||||
return sts20150401.NewClient(config)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
package logic
|
||||
|
||||
import (
|
||||
"lone-services/pkg/utils"
|
||||
chore "lone-services/rpc/chore/pb"
|
||||
|
||||
jsoniter "github.com/json-iterator/go"
|
||||
)
|
||||
|
||||
func okResponse(data any) *chore.Response {
|
||||
buf, _ := jsoniter.Marshal(data)
|
||||
return &chore.Response{
|
||||
Code: utils.Ok.Code,
|
||||
Msg: utils.Ok.Msg,
|
||||
Data: string(buf),
|
||||
}
|
||||
}
|
||||
|
||||
func failResponse(status utils.Status) *chore.Response {
|
||||
return &chore.Response{
|
||||
Code: status.Code,
|
||||
Msg: status.Msg,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user