github.com/cloudreve/Cloudreve/v3@v3.0.0-20240224133659-3edb00a6484c/pkg/filesystem/driver/oss/callback.go (about) 1 package oss 2 3 import ( 4 "bytes" 5 "crypto" 6 "crypto/md5" 7 "crypto/rsa" 8 "crypto/x509" 9 "encoding/base64" 10 "encoding/pem" 11 "errors" 12 "fmt" 13 "io/ioutil" 14 "net/http" 15 "net/url" 16 "strings" 17 18 "github.com/cloudreve/Cloudreve/v3/pkg/cache" 19 "github.com/cloudreve/Cloudreve/v3/pkg/request" 20 ) 21 22 // GetPublicKey 从回调请求或缓存中获取OSS的回调签名公钥 23 func GetPublicKey(r *http.Request) ([]byte, error) { 24 var pubKey []byte 25 26 // 尝试从缓存中获取 27 pub, exist := cache.Get("oss_public_key") 28 if exist { 29 return pub.([]byte), nil 30 } 31 32 // 从请求中获取 33 pubURL, err := base64.StdEncoding.DecodeString(r.Header.Get("x-oss-pub-key-url")) 34 if err != nil { 35 return pubKey, err 36 } 37 38 // 确保这个 public key 是由 OSS 颁发的 39 if !strings.HasPrefix(string(pubURL), "http://gosspublic.alicdn.com/") && 40 !strings.HasPrefix(string(pubURL), "https://gosspublic.alicdn.com/") { 41 return pubKey, errors.New("public key url invalid") 42 } 43 44 // 获取公钥 45 client := request.NewClient() 46 body, err := client.Request("GET", string(pubURL), nil). 47 CheckHTTPResponse(200). 48 GetResponse() 49 if err != nil { 50 return pubKey, err 51 } 52 53 // 写入缓存 54 _ = cache.Set("oss_public_key", []byte(body), 86400*7) 55 56 return []byte(body), nil 57 } 58 59 func getRequestMD5(r *http.Request) ([]byte, error) { 60 var byteMD5 []byte 61 62 // 获取请求正文 63 body, err := ioutil.ReadAll(r.Body) 64 r.Body.Close() 65 if err != nil { 66 return byteMD5, err 67 } 68 r.Body = ioutil.NopCloser(bytes.NewReader(body)) 69 70 strURLPathDecode, err := url.PathUnescape(r.URL.Path) 71 if err != nil { 72 return byteMD5, err 73 } 74 75 strAuth := fmt.Sprintf("%s\n%s", strURLPathDecode, string(body)) 76 md5Ctx := md5.New() 77 md5Ctx.Write([]byte(strAuth)) 78 byteMD5 = md5Ctx.Sum(nil) 79 80 return byteMD5, nil 81 } 82 83 // VerifyCallbackSignature 验证OSS回调请求 84 func VerifyCallbackSignature(r *http.Request) error { 85 bytePublicKey, err := GetPublicKey(r) 86 if err != nil { 87 return err 88 } 89 90 byteMD5, err := getRequestMD5(r) 91 if err != nil { 92 return err 93 } 94 95 strAuthorizationBase64 := r.Header.Get("authorization") 96 if strAuthorizationBase64 == "" { 97 return errors.New("no authorization field in Request header") 98 } 99 authorization, _ := base64.StdEncoding.DecodeString(strAuthorizationBase64) 100 101 pubBlock, _ := pem.Decode(bytePublicKey) 102 if pubBlock == nil { 103 return errors.New("pubBlock not exist") 104 } 105 pubInterface, err := x509.ParsePKIXPublicKey(pubBlock.Bytes) 106 if (pubInterface == nil) || (err != nil) { 107 return err 108 } 109 pub := pubInterface.(*rsa.PublicKey) 110 111 errorVerifyPKCS1v15 := rsa.VerifyPKCS1v15(pub, crypto.MD5, byteMD5, authorization) 112 if errorVerifyPKCS1v15 != nil { 113 return errorVerifyPKCS1v15 114 } 115 116 return nil 117 }