2019-10-12 04:46:21 -04:00
|
|
|
|
package ufsdk
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"crypto/hmac"
|
|
|
|
|
"crypto/sha1"
|
|
|
|
|
"encoding/base64"
|
|
|
|
|
"fmt"
|
|
|
|
|
"io"
|
|
|
|
|
"net/http"
|
|
|
|
|
"net/url"
|
|
|
|
|
"sort"
|
|
|
|
|
"strings"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
//Auth 构造签名的工具,使用本 SDK 你不需要关心 Auth 这一整个模块,以及它暴露出来的签名算法。
|
|
|
|
|
//如果你希望自己封装 API 可以使用这里面的暴露出来的接口来填充 http authorization。
|
|
|
|
|
type Auth struct {
|
|
|
|
|
publicKey string
|
|
|
|
|
privateKey string
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//NewAuth 构造一个新的签名工具,传入你的公钥匙和私钥。
|
|
|
|
|
func NewAuth(publicKey, privateKey string) Auth {
|
|
|
|
|
return Auth{
|
|
|
|
|
publicKey: publicKey,
|
|
|
|
|
privateKey: privateKey,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//Authorization 构造一个主要用于上传文件的签名,返回 HMAC-Sh1 的签名字符串,可以直接填充到 HTTP authorization header 里面。
|
|
|
|
|
//key 是传到 ufile 所使用的文件名,bucekt 是文件上传后存放的 bucket。
|
|
|
|
|
//method 就是你当前这个 HTTP 请求的 Method。
|
2019-10-30 13:48:41 -04:00
|
|
|
|
//header 就是你当前这个 HTTP 的 header。
|
2019-10-12 04:46:21 -04:00
|
|
|
|
func (A Auth) Authorization(method, bucket, key string, header http.Header) string {
|
|
|
|
|
var sigData string
|
|
|
|
|
method = strings.ToUpper(method)
|
|
|
|
|
|
|
|
|
|
md5 := header.Get("Content-MD5")
|
|
|
|
|
contentType := header.Get("Content-Type")
|
|
|
|
|
date := header.Get("Date")
|
|
|
|
|
|
|
|
|
|
sigData = method + "\n" + md5 + "\n" + contentType + "\n" + date + "\n"
|
2019-10-30 13:48:41 -04:00
|
|
|
|
sigData += A.CanonicalizedUcloudHeaders(header)
|
2019-10-12 04:46:21 -04:00
|
|
|
|
resource := "/" + bucket + "/" + key
|
|
|
|
|
sigData += resource
|
|
|
|
|
|
|
|
|
|
signature := A.signature(sigData)
|
|
|
|
|
|
|
|
|
|
return "UCloud " + A.publicKey + ":" + signature
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//AuthorizationPrivateURL 构造私有空间文件下载链接的签名,其中 expires 是当前的时间加上一个过期的时间,再转为字符串。格式是 unix time second.
|
|
|
|
|
//其他的参数含义和 Authoriazation 函数一样。
|
|
|
|
|
//有时我们需要把签名后的 URL 直接拿来用,header 参数可以直接构造一个空的 http.Header{} 传入即可。
|
|
|
|
|
func (A Auth) AuthorizationPrivateURL(method, bucket, key, expires string, header http.Header) (string, string) {
|
|
|
|
|
var sigData string
|
|
|
|
|
method = strings.ToUpper(method)
|
|
|
|
|
md5 := header.Get("Content-MD5")
|
|
|
|
|
contentType := header.Get("Content-Type")
|
|
|
|
|
|
|
|
|
|
sigData = method + "\n" + md5 + "\n" + contentType + "\n" + expires + "\n"
|
|
|
|
|
resource := "/" + bucket + "/" + key
|
|
|
|
|
sigData += resource
|
|
|
|
|
|
|
|
|
|
signature := A.signature(sigData)
|
|
|
|
|
|
|
|
|
|
return signature, A.publicKey
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//AuthorizationPolicy 构造支持回调策略的签名,policy 是经过 base64 编码后的 json string。
|
|
|
|
|
//本签名函数就是多了一个 policy 字段,其他的参数和 Authoriazation 一样。
|
|
|
|
|
func (A Auth) AuthorizationPolicy(method, bucket, key, policy string, header http.Header) string {
|
|
|
|
|
var sigData string
|
|
|
|
|
method = strings.ToUpper(method)
|
|
|
|
|
|
|
|
|
|
md5 := header.Get("Content-MD5")
|
|
|
|
|
contentType := header.Get("Content-Type")
|
|
|
|
|
date := header.Get("Date")
|
|
|
|
|
|
|
|
|
|
sigData = method + "\n" + md5 + "\n" + contentType + "\n" + date + "\n"
|
|
|
|
|
resource := "/" + bucket + "/" + key
|
|
|
|
|
sigData += resource
|
|
|
|
|
sigData += policy
|
|
|
|
|
|
|
|
|
|
signature := A.signature(sigData)
|
|
|
|
|
|
|
|
|
|
return "UCloud " + A.publicKey + ":" + signature + ":" + policy
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (A Auth) signature(data string) string {
|
|
|
|
|
mac := hmac.New(sha1.New, []byte(A.privateKey))
|
|
|
|
|
mac.Write([]byte(data))
|
|
|
|
|
|
|
|
|
|
return base64.StdEncoding.EncodeToString(mac.Sum(nil))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//AuthorizationBucketMgr 生成用于管理 bucket 的签名。
|
|
|
|
|
func (A Auth) AuthorizationBucketMgr(query url.Values) string {
|
|
|
|
|
query.Add("PublicKey", A.publicKey)
|
|
|
|
|
|
|
|
|
|
var signstring string
|
|
|
|
|
var keys []string
|
|
|
|
|
for k := range query {
|
|
|
|
|
keys = append(keys, k)
|
|
|
|
|
}
|
|
|
|
|
sort.Strings(keys)
|
|
|
|
|
for _, k := range keys {
|
|
|
|
|
signstring += k + query.Get(k) //Get first value
|
|
|
|
|
}
|
|
|
|
|
signstring += A.privateKey
|
|
|
|
|
|
|
|
|
|
h := sha1.New()
|
|
|
|
|
io.WriteString(h, signstring)
|
|
|
|
|
|
|
|
|
|
query.Add("Signature", fmt.Sprintf("%x", h.Sum(nil)))
|
|
|
|
|
return query.Encode()
|
|
|
|
|
}
|
2019-10-30 13:48:41 -04:00
|
|
|
|
|
|
|
|
|
//CanonicalizedUcloudHeaders 用于将自定义请求报头规范化为string
|
|
|
|
|
//ucloudHeader 支持自定义请求头
|
|
|
|
|
func (A Auth) CanonicalizedUcloudHeaders(ucloudHeader http.Header) string {
|
|
|
|
|
keys := make([]string, 0)
|
|
|
|
|
headers := make(map[string]string, 0)
|
|
|
|
|
for k := range ucloudHeader {
|
|
|
|
|
newkey := strings.ToLower(k)
|
|
|
|
|
if strings.HasPrefix(newkey, "x-ufile-") || strings.HasPrefix(newkey, "x-ucloud-") {
|
|
|
|
|
headers[newkey] = strings.TrimSpace(ucloudHeader[k][0])
|
|
|
|
|
keys = append(keys, newkey)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
sort.Strings(keys)
|
|
|
|
|
|
|
|
|
|
s := ""
|
|
|
|
|
for _, k := range keys {
|
|
|
|
|
v := headers[k]
|
|
|
|
|
s += k + ":" + v + "\n"
|
|
|
|
|
}
|
|
|
|
|
return s
|
|
|
|
|
}
|