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
 | |
| }
 |