我在 gcloud 中有一个配置了存储桶后端的 CDN,该存储桶是私有的,我将ObjectViewer
权限授予 CDN 服务帐户 ( serviceAccount:service-XXXX@cloud-cdn-fill.iam.gserviceaccount.com
)
我有一个 API 可以从 CDN 请求文件:
- 此 API 检查是否允许用户下载请求的文件
- 使用 CDN URL 计算此文件的签名 URL
- 使用计算的签名 url 重定向用户
大多数情况下,客户端成功下载文件并接收200
,但是当我的客户端(移动应用程序)被重定向到签名 URL 时,我随机出现错误:
<?xml version='1.0' encoding='UTF-8'?><Error><Code>AuthenticationRequired</Code><Message>Authentication required.</Message></Error>
生成新的签名 URL 无法解决此问题:错误是在 X 分钟/秒内发送的。
我的 API 回复301
并没有触发授权错误。此错误是由 CND HTTP 负载平衡器发送的,带有状态代码401
。
这是我生成签名 URL 的函数:
func signURL(url string) (string, errors.Mwm) {
expirationTime := time.Now().UTC().Add(internal.DefaultSignedURLValidTime).Unix()
cdnKeyValue, err := internal.GetCDNSignKeyValue()
if err != nil {
return "", err
}
sep := "?"
if strings.Contains(url, "?") {
sep = "&"
}
url += sep
url += fmt.Sprintf("Expires=%d", expirationTime)
url += fmt.Sprintf("&KeyName=%s", internal.CdnSignKeyName)
mac := hmac.New(sha1.New, cdnKeyValue)
mac.Write([]byte(url))
sig := base64.URLEncoding.EncodeToString(mac.Sum(nil))
url += fmt.Sprintf("&Signature=%s", sig)
return url, nil
}