时间戳防盗链(七牛云 oss 为例)的实现过程

每个对象存储服务商都会提供时间戳防盗链的支持,原理基本一样,本文以七牛云为例,服务端是用 Go 实现的 API。

生成签名的 url 的时候,也要将新生成的 url 保存到 redis 中,防止每次访问都生成新的签名,即浪费服务器资源,又会增加 CDN 流量。

签名代码:

// Sign 每一个图片生成 2 分钟有效期的签名
//
// imgPath 是图片路径,不是完整链接。
func Sign(imgPath string) (string, error) {
	var (
		// 七牛云设置的签名的 Key
		key = "xxxxxxxxxx"
	
		// 过期时间
		expire = time.Now().Unix() + 60*2
	)

	rawStr := fmt.Sprintf("%s/%s%x", key, imgPath, expire)

	hash := md5.New()
	hash.Write([]byte(rawStr))

	sign := fmt.Sprintf("%x", hash.Sum(nil))

	var newPath string

	newPath = fmt.Sprintf("%s?sign=%s&t=%x", imgPath, sign, expire)
  
	// 生成签名后放进 redis 中,过期时间比签名过期时间短 1 秒,下次再访问时先从 redis 中查找签名过的链接
	err := redis.CacheSignedURL(imgPath, newPath, 60*2-1)
	if err != nil {
		return "", err
	}

	return newPath, nil
}

如果下次访问时没有从 redis 中获取到签名的 url ,再生成新的签名,伪码:

func GetSignedURL(url string) string {
	cache := redis.GetCacheSignedURL(url)
	if cache != "" {
		return cache
	}
	return Sign(url)
}

这样的好处就是在有效期内服务端返回的图片链接不会改变,浏览器就能够缓存有效期内的图片。

当过有效期时,服务端返回新的签名链接,浏览器就会向七牛 CDN 发出新的请求,进行新一轮的有效期内缓存。

前端从响应 json 中拿到的签名链接渲染页面。


有效期内会在浏览器中缓存:

截屏2021-05-12 10.56.12

过了有效期就返回 403:

截屏2021-05-12 10.57.49

posted @ 2021-05-12 10:59  thepoy  阅读(549)  评论(0编辑  收藏  举报