81 lines
2.5 KiB
Go
81 lines
2.5 KiB
Go
|
package auth
|
||
|
|
||
|
import (
|
||
|
"crypto/md5"
|
||
|
"fmt"
|
||
|
"net/url"
|
||
|
"time"
|
||
|
)
|
||
|
|
||
|
// An URLSigner provides URL signing utilities to sign URLs for Aliyun CDN
|
||
|
// resources.
|
||
|
// authentication document: https://help.aliyun.com/document_detail/85117.html
|
||
|
type URLSigner struct {
|
||
|
authType string
|
||
|
privKey string
|
||
|
}
|
||
|
|
||
|
// NewURLSigner returns a new signer object.
|
||
|
func NewURLSigner(authType string, privKey string) *URLSigner {
|
||
|
return &URLSigner{
|
||
|
authType: authType,
|
||
|
privKey: privKey,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Sign returns a signed aliyuncdn url based on authentication type
|
||
|
func (s URLSigner) Sign(uri string, expires time.Time) (string, error) {
|
||
|
r, err := url.Parse(uri)
|
||
|
if err != nil {
|
||
|
return "", fmt.Errorf("unable to parse url: %s", uri)
|
||
|
}
|
||
|
|
||
|
switch s.authType {
|
||
|
case "a":
|
||
|
return aTypeSign(r, s.privKey, expires), nil
|
||
|
case "b":
|
||
|
return bTypeSign(r, s.privKey, expires), nil
|
||
|
case "c":
|
||
|
return cTypeSign(r, s.privKey, expires), nil
|
||
|
default:
|
||
|
return "", fmt.Errorf("invalid authentication type")
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// sign by A type authentication method.
|
||
|
// authentication document: https://help.aliyun.com/document_detail/85113.html
|
||
|
func aTypeSign(r *url.URL, privateKey string, expires time.Time) string {
|
||
|
//rand is a random uuid without "-"
|
||
|
rand := GenerateUUID().String()
|
||
|
// not use, "0" by default
|
||
|
uid := "0"
|
||
|
secret := fmt.Sprintf("%s-%d-%s-%s-%s", r.Path, expires.Unix(), rand, uid, privateKey)
|
||
|
hashValue := md5.Sum([]byte(secret))
|
||
|
authKey := fmt.Sprintf("%d-%s-%s-%x", expires.Unix(), rand, uid, hashValue)
|
||
|
if r.RawQuery == "" {
|
||
|
return fmt.Sprintf("%s?auth_key=%s", r.String(), authKey)
|
||
|
}
|
||
|
return fmt.Sprintf("%s&auth_key=%s", r.String(), authKey)
|
||
|
|
||
|
}
|
||
|
|
||
|
// sign by B type authentication method.
|
||
|
// authentication document: https://help.aliyun.com/document_detail/85114.html
|
||
|
func bTypeSign(r *url.URL, privateKey string, expires time.Time) string {
|
||
|
formatExp := expires.Format("200601021504")
|
||
|
secret := privateKey + formatExp + r.Path
|
||
|
hashValue := md5.Sum([]byte(secret))
|
||
|
signURL := fmt.Sprintf("%s://%s/%s/%x%s?%s", r.Scheme, r.Host, formatExp, hashValue, r.Path, r.RawQuery)
|
||
|
return signURL
|
||
|
}
|
||
|
|
||
|
// sign by C type authentication method.
|
||
|
// authentication document: https://help.aliyun.com/document_detail/85115.html
|
||
|
func cTypeSign(r *url.URL, privateKey string, expires time.Time) string {
|
||
|
hexExp := fmt.Sprintf("%x", expires.Unix())
|
||
|
secret := privateKey + r.Path + hexExp
|
||
|
hashValue := md5.Sum([]byte(secret))
|
||
|
signURL := fmt.Sprintf("%s://%s/%x/%s%s?%s", r.Scheme, r.Host, hashValue, hexExp, r.Path, r.RawQuery)
|
||
|
return signURL
|
||
|
}
|