mirror of
				https://github.com/cloudreve/cloudreve.git
				synced 2025-10-31 08:39:10 +08:00 
			
		
		
		
	Modify: oss handle sign URL
This commit is contained in:
		| @ -217,7 +217,9 @@ func (policy *Policy) GetUploadURL() string { | |||||||
| 		return "/api/v3/file/upload" | 		return "/api/v3/file/upload" | ||||||
| 	case "remote": | 	case "remote": | ||||||
| 		controller, _ = url.Parse("/api/v3/slave/upload") | 		controller, _ = url.Parse("/api/v3/slave/upload") | ||||||
| 	case "oss", "cos": | 	case "oss": | ||||||
|  | 		return "https://" + policy.BucketName + "." + policy.Server | ||||||
|  | 	case "cos": | ||||||
| 		return policy.BaseURL | 		return policy.BaseURL | ||||||
| 	case "upyun": | 	case "upyun": | ||||||
| 		return "http://v0.api.upyun.com/" + policy.BucketName | 		return "http://v0.api.upyun.com/" + policy.BucketName | ||||||
|  | |||||||
| @ -49,6 +49,30 @@ const ( | |||||||
| 	VersionID key = iota | 	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鉴权客户端 | // InitOSSClient 初始化OSS鉴权客户端 | ||||||
| func (handler *Driver) InitOSSClient() error { | func (handler *Driver) InitOSSClient() error { | ||||||
| 	if handler.Policy == nil { | 	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) { | 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...) | 	signedURL, err := handler.bucket.SignURL(path, oss.HTTPGet, ttl, options...) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return "", err | 		return "", err | ||||||
| @ -269,8 +272,26 @@ func (handler Driver) signSourceURL(ctx context.Context, path string, ttl int64, | |||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return "", err | 		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 | 	return finalURL.String(), nil | ||||||
| } | } | ||||||
| @ -301,10 +322,14 @@ func (handler Driver) Token(ctx context.Context, TTL int64, key string) (seriali | |||||||
| 		Conditions: []interface{}{ | 		Conditions: []interface{}{ | ||||||
| 			map[string]string{"bucket": handler.Policy.BucketName}, | 			map[string]string{"bucket": handler.Policy.BucketName}, | ||||||
| 			[]string{"starts-with", "$key", path.Dir(savePath)}, | 			[]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) | 	return handler.getUploadCredential(ctx, postPolicy, callbackPolicy, TTL) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | |||||||
| @ -154,7 +154,7 @@ func (fs *FileSystem) GetUploadToken(ctx context.Context, path string, size uint | |||||||
| 	// 是否需要预先生成存储路径 | 	// 是否需要预先生成存储路径 | ||||||
| 	var savePath string | 	var savePath string | ||||||
| 	if fs.User.Policy.IsPathGenerateNeeded() { | 	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.SavePathCtx, savePath) | ||||||
| 	} | 	} | ||||||
| 	ctx = context.WithValue(ctx, fsctx.FileSizeCtx, size) | 	ctx = context.WithValue(ctx, fsctx.FileSizeCtx, size) | ||||||
|  | |||||||
| @ -172,3 +172,14 @@ func AdminAddPolicy(c *gin.Context) { | |||||||
| 		c.JSON(200, ErrorResponse(err)) | 		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)) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | |||||||
| @ -334,6 +334,8 @@ func InitMasterRouter() *gin.Engine { | |||||||
| 					policy.POST("test/slave", controllers.AdminTestSlave) | 					policy.POST("test/slave", controllers.AdminTestSlave) | ||||||
| 					// 创建存储策略 | 					// 创建存储策略 | ||||||
| 					policy.POST("", controllers.AdminAddPolicy) | 					policy.POST("", controllers.AdminAddPolicy) | ||||||
|  | 					// 创建存储策略 | ||||||
|  | 					policy.POST("cors", controllers.AdminAddCORS) | ||||||
| 				} | 				} | ||||||
|  |  | ||||||
| 			} | 			} | ||||||
|  | |||||||
| @ -7,6 +7,7 @@ import ( | |||||||
| 	model "github.com/HFO4/cloudreve/models" | 	model "github.com/HFO4/cloudreve/models" | ||||||
| 	"github.com/HFO4/cloudreve/pkg/auth" | 	"github.com/HFO4/cloudreve/pkg/auth" | ||||||
| 	"github.com/HFO4/cloudreve/pkg/conf" | 	"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/request" | ||||||
| 	"github.com/HFO4/cloudreve/pkg/serializer" | 	"github.com/HFO4/cloudreve/pkg/serializer" | ||||||
| 	"github.com/HFO4/cloudreve/pkg/util" | 	"github.com/HFO4/cloudreve/pkg/util" | ||||||
| @ -37,6 +38,34 @@ type AddPolicyService struct { | |||||||
| 	Policy model.Policy `json:"policy" binding:"required"` | 	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 | // Test 从机响应ping | ||||||
| func (service *SlavePingService) Test() serializer.Response { | func (service *SlavePingService) Test() serializer.Response { | ||||||
| 	master, err := url.Parse(service.Callback) | 	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 { | 	if err := model.DB.Create(&service.Policy).Error; err != nil { | ||||||
| 		return serializer.ParamErr("存储策略添加失败", err) | 		return serializer.ParamErr("存储策略添加失败", err) | ||||||
| 	} | 	} | ||||||
| 	return serializer.Response{} | 	return serializer.Response{Data: service.Policy.ID} | ||||||
| } | } | ||||||
|  |  | ||||||
| // Test 测试本地路径 | // Test 测试本地路径 | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user
	 HFO4
					HFO4