3 Star 1 Fork 0

Gitee 极速下载 / aws-sdk-go

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
此仓库是为了提升国内下载速度的镜像仓库,每日同步一次。 原始仓库: https://github.com/aws/aws-sdk-go
克隆/下载
sign_url.go 6.38 KB
一键复制 编辑 原始数据 按行查看 历史
Quest Henkart 提交于 2016-03-29 12:25 . Update sign_url.go
// Package sign provides utilities to generate signed URLs for Amazon CloudFront.
//
// More information about signed URLs and their structure can be found at:
// http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-creating-signed-url-canned-policy.html
//
// To sign a URL create a URLSigner with your private key and credential pair key ID.
// Once you have a URLSigner instance you can call Sign or SignWithPolicy to
// sign the URLs.
//
// Example:
//
// // Sign URL to be valid for 1 hour from now.
// signer := sign.NewURLSigner(keyID, privKey)
// signedURL, err := signer.Sign(rawURL, time.Now().Add(1*time.Hour))
// if err != nil {
// log.Fatalf("Failed to sign url, err: %s\n", err.Error())
// }
//
package sign
import (
"crypto/rsa"
"fmt"
"net/url"
"strings"
"time"
)
// An URLSigner provides URL signing utilities to sign URLs for Amazon CloudFront
// resources. Using a private key and Credential Key Pair key ID the URLSigner
// only needs to be created once per Credential Key Pair key ID and private key.
//
// The signer is safe to use concurrently.
type URLSigner struct {
keyID string
privKey *rsa.PrivateKey
}
// NewURLSigner constructs and returns a new URLSigner to be used to for signing
// Amazon CloudFront URL resources with.
func NewURLSigner(keyID string, privKey *rsa.PrivateKey) *URLSigner {
return &URLSigner{
keyID: keyID,
privKey: privKey,
}
}
// Sign will sign a single URL to expire at the time of expires sign using the
// Amazon CloudFront default Canned Policy. The URL will be signed with the
// private key and Credential Key Pair Key ID previously provided to URLSigner.
//
// This is the default method of signing Amazon CloudFront URLs. If extra policy
// conditions are need other than URL expiry use SignWithPolicy instead.
//
// Example:
//
// // Sign URL to be valid for 1 hour from now.
// signer := sign.NewURLSigner(keyID, privKey)
// signedURL, err := signer.Sign(rawURL, time.Now().Add(1*time.Hour))
// if err != nil {
// log.Fatalf("Failed to sign url, err: %s\n", err.Error())
// }
//
func (s URLSigner) Sign(url string, expires time.Time) (string, error) {
scheme, cleanedURL, err := cleanURLScheme(url)
if err != nil {
return "", err
}
resource, err := CreateResource(scheme, url)
if err != nil {
return "", err
}
return signURL(scheme, cleanedURL, s.keyID, NewCannedPolicy(resource, expires), false, s.privKey)
}
// SignWithPolicy will sign a URL with the Policy provided. The URL will be
// signed with the private key and Credential Key Pair Key ID previously provided to URLSigner.
//
// Use this signing method if you are looking to sign a URL with more than just
// the URL's expiry time, or reusing Policies between multiple URL signings.
// If only the expiry time is needed you can use Sign and provide just the
// URL's expiry time. A minimum of at least one policy statement is required for a signed URL.
//
// Note: It is not safe to use Polices between multiple signers concurrently
//
// Example:
//
// // Sign URL to be valid for 30 minutes from now, expires one hour from now, and
// // restricted to the 192.0.2.0/24 IP address range.
// policy := &sign.Policy{
// Statements: []sign.Statement{
// {
// Resource: rawURL,
// Condition: sign.Condition{
// // Optional IP source address range
// IPAddress: &sign.IPAddress{SourceIP: "192.0.2.0/24"},
// // Optional date URL is not valid until
// DateGreaterThan: &sign.AWSEpochTime{time.Now().Add(30 * time.Minute)},
// // Required date the URL will expire after
// DateLessThan: &sign.AWSEpochTime{time.Now().Add(1 * time.Hour)},
// },
// },
// },
// }
//
// signer := sign.NewURLSigner(keyID, privKey)
// signedURL, err := signer.SignWithPolicy(rawURL, policy)
// if err != nil {
// log.Fatalf("Failed to sign url, err: %s\n", err.Error())
// }
//
func (s URLSigner) SignWithPolicy(url string, p *Policy) (string, error) {
scheme, cleanedURL, err := cleanURLScheme(url)
if err != nil {
return "", err
}
return signURL(scheme, cleanedURL, s.keyID, p, true, s.privKey)
}
func signURL(scheme, url, keyID string, p *Policy, customPolicy bool, privKey *rsa.PrivateKey) (string, error) {
// Validation URL elements
if err := validateURL(url); err != nil {
return "", err
}
b64Signature, b64Policy, err := p.Sign(privKey)
if err != nil {
return "", err
}
// build and return signed URL
builtURL := buildSignedURL(url, keyID, p, customPolicy, b64Policy, b64Signature)
if scheme == "rtmp" {
return buildRTMPURL(builtURL)
}
return builtURL, nil
}
func buildSignedURL(baseURL, keyID string, p *Policy, customPolicy bool, b64Policy, b64Signature []byte) string {
pred := "?"
if strings.Contains(baseURL, "?") {
pred = "&"
}
signedURL := baseURL + pred
if customPolicy {
signedURL += "Policy=" + string(b64Policy)
} else {
signedURL += fmt.Sprintf("Expires=%d", p.Statements[0].Condition.DateLessThan.UTC().Unix())
}
signedURL += fmt.Sprintf("&Signature=%s&Key-Pair-Id=%s", string(b64Signature), keyID)
return signedURL
}
func buildRTMPURL(u string) (string, error) {
parsed, err := url.Parse(u)
if err != nil {
return "", fmt.Errorf("unable to parse rtmp signed URL, err: %s", err)
}
rtmpURL := strings.TrimLeft(parsed.Path, "/")
if parsed.RawQuery != "" {
rtmpURL = fmt.Sprintf("%s?%s", rtmpURL, parsed.RawQuery)
}
return rtmpURL, nil
}
func cleanURLScheme(u string) (scheme, cleanedURL string, err error) {
parts := strings.SplitN(u, "://", 2)
if len(parts) != 2 {
return "", "", fmt.Errorf("invalid URL, missing scheme and domain/path")
}
scheme = strings.Replace(parts[0], "*", "", 1)
cleanedURL = fmt.Sprintf("%s://%s", scheme, parts[1])
return strings.ToLower(scheme), cleanedURL, nil
}
var illegalQueryParms = []string{"Expires", "Policy", "Signature", "Key-Pair-Id"}
func validateURL(u string) error {
parsed, err := url.Parse(u)
if err != nil {
return fmt.Errorf("unable to parse URL, err: %s", err.Error())
}
if parsed.Scheme == "" {
return fmt.Errorf("URL missing valid scheme, %s", u)
}
q := parsed.Query()
for _, p := range illegalQueryParms {
if _, ok := q[p]; ok {
return fmt.Errorf("%s cannot be a query parameter for a signed URL", p)
}
}
return nil
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/mirrors/aws-sdk-go.git
git@gitee.com:mirrors/aws-sdk-go.git
mirrors
aws-sdk-go
aws-sdk-go
v1.1.22

搜索帮助

344bd9b3 5694891 D2dac590 5694891