一文搞定防盗链设计

大家好,我是蓝胖子,在涉及到图片或者视频链接时,通常都会提到防盗链,这一节我将会从防盗链的含义到落地,向大家展示如何设计资源的防盗链。

防盗链的含义与作用

防盗链,顾名思义,是为了防止资源被他人窃取而设计的。

通常我们将图片或视频链接存储到obs对象存储上,前端通过服务端返回的图片或视频链接访问obs上对应的资源,那如果这个链接被第三方网站获取到,便能在其网站上直接访问我们的视频或者图片资源。

防盗链的出现就是为了杜绝第三方网站能直接访问我们的视频或图片资源。让返回的资源链接只能被我们指定的网站进行访问

防盗链方案设计

接着,我以华为云的obs系统 为例, 讲几个关于防盗链的设计方案,供大家参考,

refer指定黑白名单

浏览器在加载静态资源时,会在请求头中加上Refer字段,其值为浏览器当前的网址,目的是为了告诉服务器,用户在访问资源之前的位置。

如果第三方网站获盗取到了我们的视频资源,那么在其访问时,Refer就是第三方网站的网址,我们可以在obs上配置reder黑白名单,指定资源让某些网站不允许访问或者对某些网站允许访问。

更加灵活的鉴权方式-远程鉴权

除此以外,还有种更加灵活的鉴权方式,通过自定义的代码来判断该访问链接是否允许被访问。在使用obs系统时,为了减少带宽成本,我们将会在obs前面,部署cdn节点,让用户访问的资源能够被缓存到离他比较近的cdn节点上。

通常cdn节点上可以配置对应的访问,例如华为云可以配置远程鉴权的地址,指向自己的服务器鉴权接口,在接口中定义对资源的访问权限,像cloudflare则是可以创建worker,在worker中定义链接的访问权限。

鉴权逻辑应该如何写,这里我提供一个比较通用的逻辑,给大家参考下。

在服务端返回给客户端资源在obs上的访问链接时,可以加上该链接的创建时间,在鉴权逻辑里申明一个链接的有效期,根据链接的产生时间和有效期 允许该链接在有效期内允许访问,比如返回给客户端的链接是

shell 复制代码
https://xxx?ctime=1711962048

ctime 则是链接的创建时间,但是仅仅这样是不够的,第三方网站可以获取到链接后修改ctime字段来修改链接的创建时间,所以我们还需要一个消息认证的机制,保证链接是服务器返回的且没有经过篡改,这里可以用消息认证算法实现。

拿消息认证算法hmac举例,服务器端定义一个只有自己知道的密钥,用该密钥对资源地址进行md5的摘要计算,如下是golang中的hamc的使用逻辑,

golang 复制代码
key := "hamcsecrete"
    data := "https://xxx?ctime=1711962048"
    hmac := hmac.New(md5.New, []byte(key))
    hmac.Write([]byte(data))
    fmt.Println(hex.EncodeToString(hmac.Sum([]byte(""))))

得到的消息认证码,加入到资源链接的参数中,如下,

https://xxx?ctime=1711962048&token=679f5d6f7d344dba1e33938ae1d41ab4

这样,鉴权服务器在得到资源链接时,就会将资源地址通过同样的消息认证算法和密钥计算token值,如果计算出的token值和资源链接中的token值一致,则继续查看链接是否在有效期范围内,在则允许访问,否则不允许访问。因为消息认证的密钥只有服务器知道,即使第三方网站获取到了链接,也无法得出正确的token值。

最后,在使用此逻辑的时候,要注意cdn服务器回源的条件,通常cdn是根据url路径查看是否需要回源,如果url地址不同,则会去访问源站服务器,我们当然不希望因为链接ctime的不同就再次去请求源站服务器,所以,在cdn节点处,需要配置,判断回源时需要忽略ctime和token的参数。