通用包
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
utils/sign_oss_mid/v1/sign.go

126 lines
2.8 KiB

package v1
import (
"context"
"encoding/json"
"errors"
"net/url"
"regexp"
"strings"
"gitea.drugeyes.vip/pharnexbase/utils/pkg/set"
"github.com/aliyun/aliyun-oss-go-sdk/oss"
"github.com/go-kratos/kratos/v2/middleware"
"github.com/go-kratos/kratos/v2/transport"
)
type Signer struct {
client *oss.Client
bucketsWl []string
expiredInSec int64 // 默认 7 天有效期
}
func NewSigner(client *oss.Client) *Signer {
return &Signer{
client: client,
expiredInSec: 604800,
}
}
type UrlInfo struct {
Bucket string
Endpoint string
Object string
FileName string
}
func (s *Signer) SetBucketsWhiteList(bucketsWl []string) *Signer {
s.bucketsWl = bucketsWl
return s
}
func (s *Signer) SetExpiredInSec(expiredInSec int64) *Signer {
s.expiredInSec = expiredInSec
return s
}
func (s *Signer) SignUrl() middleware.Middleware {
return func(handler middleware.Handler) middleware.Handler {
return func(ctx context.Context, req interface{}) (reply interface{}, err error) {
reply, err = handler(ctx, req)
if err != nil {
return
}
if _, ok := transport.FromServerContext(ctx); ok {
// 后置匹配 oss 地址,签名 url,替换输出
var marshal []byte
marshal, err = json.Marshal(reply)
if err != nil {
return
}
jsonStr := string(marshal)
r := regexp.MustCompile("\"(https?://[-.a-z0-9]+\\.aliyuncs\\.com/[^\"\\\\]+)\\\\*\"")
res := r.FindAllStringSubmatch(jsonStr, -1)
for _, mu := range res {
urlInfo, ue := GetUrlInfo(mu[1]) // url错误则不处理,用户中心不处理
if ue == nil && !set.NewSetWithItems(s.bucketsWl...).Has(urlInfo.Bucket){
var bucket *oss.Bucket
bucket, err = s.client.Bucket(urlInfo.Bucket)
if err != nil {
return
}
// 生成用于下载的签名URL,并指定签名URL的有效时间。
var surl string
surl, err = bucket.SignURL(urlInfo.Object, oss.HTTPGet, s.expiredInSec)
if err != nil {
return
}
// 使用签名url替换原始url
jsonStr = strings.Replace(jsonStr, mu[1], surl, -1)
}
}
// 覆盖原始输出
err = json.Unmarshal([]byte(jsonStr), reply)
if err != nil {
return
}
}
return
}
}
}
func GetUrlInfo(ossUrl string) (*UrlInfo, error) {
parse, err := url.Parse(ossUrl)
if err != nil {
return nil, err
}
hostInfo := strings.SplitN(parse.Host, ".", 2)
if len(hostInfo) != 2 {
return nil, errors.New("oss url error")
}
object := strings.TrimLeft(parse.Path, "/")
if object == "" {
return nil, errors.New("oss url error")
}
objectInfo := strings.Split(object, "/")
if len(object) == 0 {
return nil, errors.New("oss url error")
}
fileName := objectInfo[len(objectInfo)-1]
return &UrlInfo{
Bucket: hostInfo[0],
Endpoint: hostInfo[1],
Object: object,
FileName: fileName,
}, err
}