From c4eada27239bd25cc8fa737a850fb195a679ae2c Mon Sep 17 00:00:00 2001 From: HFO4 <912394456@qq.com> Date: Thu, 27 Feb 2020 15:12:15 +0800 Subject: [PATCH] Modify: oss handle sign URL --- models/policy.go | 4 +- pkg/filesystem/driver/oss/handller.go | 73 ++++++++++++++++++--------- pkg/filesystem/upload.go | 2 +- routers/controllers/admin.go | 11 ++++ routers/router.go | 2 + service/admin/policy.go | 31 +++++++++++- 6 files changed, 96 insertions(+), 27 deletions(-) diff --git a/models/policy.go b/models/policy.go index 87f8b01..325c876 100644 --- a/models/policy.go +++ b/models/policy.go @@ -217,7 +217,9 @@ func (policy *Policy) GetUploadURL() string { return "/api/v3/file/upload" case "remote": controller, _ = url.Parse("/api/v3/slave/upload") - case "oss", "cos": + case "oss": + return "https://" + policy.BucketName + "." + policy.Server + case "cos": return policy.BaseURL case "upyun": return "http://v0.api.upyun.com/" + policy.BucketName diff --git a/pkg/filesystem/driver/oss/handller.go b/pkg/filesystem/driver/oss/handller.go index aec07c8..47610ea 100644 --- a/pkg/filesystem/driver/oss/handller.go +++ b/pkg/filesystem/driver/oss/handller.go @@ -49,6 +49,30 @@ const ( VersionID key = iota ) +// CORS 创建跨域策略 +func (handler *Driver) CORS() error { + // 初始化客户端 + if err := handler.InitOSSClient(); err != nil { + return err + } + + return handler.client.SetBucketCORS(handler.Policy.BucketName, []oss.CORSRule{ + { + AllowedOrigin: []string{"*"}, + AllowedMethod: []string{ + "GET", + "POST", + "PUT", + "DELETE", + "HEAD", + }, + ExposeHeader: []string{}, + AllowedHeader: []string{"*"}, + MaxAgeSeconds: 3600, + }, + }) +} + // InitOSSClient 初始化OSS鉴权客户端 func (handler *Driver) InitOSSClient() error { if handler.Policy == nil { @@ -238,27 +262,6 @@ func (handler Driver) Source( } func (handler Driver) signSourceURL(ctx context.Context, path string, ttl int64, options []oss.Option) (string, error) { - cdnURL, err := url.Parse(handler.Policy.BaseURL) - if err != nil { - return "", err - } - - // 公有空间不需要签名 - if !handler.Policy.IsPrivate { - file, err := url.Parse(path) - if err != nil { - return "", err - } - sourceURL := cdnURL.ResolveReference(file) - - // 如果有缩略图设置 - if thumbSize, ok := ctx.Value(fsctx.ThumbSizeCtx).(string); ok { - sourceURL.RawQuery = "x-oss-process=" + thumbSize - } - - return sourceURL.String(), nil - } - signedURL, err := handler.bucket.SignURL(path, oss.HTTPGet, ttl, options...) if err != nil { return "", err @@ -269,8 +272,26 @@ func (handler Driver) signSourceURL(ctx context.Context, path string, ttl int64, if err != nil { return "", err } - finalURL.Host = cdnURL.Host - finalURL.Scheme = cdnURL.Scheme + + // 优先使用https + finalURL.Scheme = "https" + + // 公有空间替换掉Key + if !handler.Policy.IsPrivate { + query := finalURL.Query() + query.Del("OSSAccessKeyId") + query.Del("Signature") + finalURL.RawQuery = query.Encode() + } + + if handler.Policy.BaseURL != "" { + cdnURL, err := url.Parse(handler.Policy.BaseURL) + if err != nil { + return "", err + } + finalURL.Host = cdnURL.Host + finalURL.Scheme = cdnURL.Scheme + } return finalURL.String(), nil } @@ -301,10 +322,14 @@ func (handler Driver) Token(ctx context.Context, TTL int64, key string) (seriali Conditions: []interface{}{ map[string]string{"bucket": handler.Policy.BucketName}, []string{"starts-with", "$key", path.Dir(savePath)}, - []interface{}{"content-length-range", 0, handler.Policy.MaxSize}, }, } + if handler.Policy.MaxSize > 0 { + postPolicy.Conditions = append(postPolicy.Conditions, + []interface{}{"content-length-range", 0, handler.Policy.MaxSize}) + } + return handler.getUploadCredential(ctx, postPolicy, callbackPolicy, TTL) } diff --git a/pkg/filesystem/upload.go b/pkg/filesystem/upload.go index d2a1006..aefbede 100644 --- a/pkg/filesystem/upload.go +++ b/pkg/filesystem/upload.go @@ -154,7 +154,7 @@ func (fs *FileSystem) GetUploadToken(ctx context.Context, path string, size uint // 是否需要预先生成存储路径 var savePath string if fs.User.Policy.IsPathGenerateNeeded() { - savePath = fs.GenerateSavePath(ctx, local.FileStream{Name: name}) + savePath = fs.GenerateSavePath(ctx, local.FileStream{Name: name, VirtualPath: path}) ctx = context.WithValue(ctx, fsctx.SavePathCtx, savePath) } ctx = context.WithValue(ctx, fsctx.FileSizeCtx, size) diff --git a/routers/controllers/admin.go b/routers/controllers/admin.go index 964d385..80ba49d 100644 --- a/routers/controllers/admin.go +++ b/routers/controllers/admin.go @@ -172,3 +172,14 @@ func AdminAddPolicy(c *gin.Context) { c.JSON(200, ErrorResponse(err)) } } + +// AdminAddCORS 创建跨域策略 +func AdminAddCORS(c *gin.Context) { + var service admin.PolicyService + if err := c.ShouldBindJSON(&service); err == nil { + res := service.AddCORS() + c.JSON(200, res) + } else { + c.JSON(200, ErrorResponse(err)) + } +} diff --git a/routers/router.go b/routers/router.go index 3a29f09..4607c71 100644 --- a/routers/router.go +++ b/routers/router.go @@ -334,6 +334,8 @@ func InitMasterRouter() *gin.Engine { policy.POST("test/slave", controllers.AdminTestSlave) // 创建存储策略 policy.POST("", controllers.AdminAddPolicy) + // 创建存储策略 + policy.POST("cors", controllers.AdminAddCORS) } } diff --git a/service/admin/policy.go b/service/admin/policy.go index cde8896..24c806c 100644 --- a/service/admin/policy.go +++ b/service/admin/policy.go @@ -7,6 +7,7 @@ import ( model "github.com/HFO4/cloudreve/models" "github.com/HFO4/cloudreve/pkg/auth" "github.com/HFO4/cloudreve/pkg/conf" + "github.com/HFO4/cloudreve/pkg/filesystem/driver/oss" "github.com/HFO4/cloudreve/pkg/request" "github.com/HFO4/cloudreve/pkg/serializer" "github.com/HFO4/cloudreve/pkg/util" @@ -37,6 +38,34 @@ type AddPolicyService struct { Policy model.Policy `json:"policy" binding:"required"` } +// PolicyService 存储策略ID服务 +type PolicyService struct { + ID uint `json:"id" binding:"required"` +} + +// AddCORS 创建跨域策略 +func (service *PolicyService) AddCORS() serializer.Response { + policy, err := model.GetPolicyByID(service.ID) + if err != nil { + return serializer.Err(serializer.CodeNotFound, "存储策略不存在", nil) + } + + switch policy.Type { + case "oss": + handler := oss.Driver{ + Policy: &policy, + HTTPClient: request.HTTPClient{}, + } + if err := handler.CORS(); err != nil { + return serializer.Err(serializer.CodeInternalSetting, "跨域策略添加失败", err) + } + default: + return serializer.ParamErr("不支持此策略", nil) + } + + return serializer.Response{} +} + // Test 从机响应ping func (service *SlavePingService) Test() serializer.Response { master, err := url.Parse(service.Callback) @@ -107,7 +136,7 @@ func (service *AddPolicyService) Add() serializer.Response { if err := model.DB.Create(&service.Policy).Error; err != nil { return serializer.ParamErr("存储策略添加失败", err) } - return serializer.Response{} + return serializer.Response{Data: service.Policy.ID} } // Test 测试本地路径