nginx secure_link 防盜連方法

ngx_http_secure_link_module 是nginx 內建的一種防盜連模組,可以透過 MD5 + Expire 達成有時效性的檔案下載機制。

最近正在做的一個 Case 剛好有這需求,Google 一下各教學文,大概都是講要帶入 expire 參數於 query param 來達成防盜連
但是我看有的網站是用純目錄型式達成的,不知道是不是用 nginx 達成的,反正我找不到不加 query param 範例就自己試試修改別人範例了。

nginx 範例設定如下

     location /files {
 
         if ($request_uri ~ "/files/([a-zA-Z0-9\-_].+)/(\d+)/(.*)") {
 
                 set $hash_md5 $1;
                 set $expires $2;
                 set $filepath $3;
          }
 
         secure_link $hash_md5,$expires;
         secure_link_md5 "$expires$filepath hello";
         if ($secure_link = "") {
                 return 403;
         }
 
         if ($secure_link = "0") {
                 return 410;
         }
         rewrite ^ /secure/$filepath;
     }
 
     location /secure/ {
         internal;
         # expires 3h;
         alias /var/www/your-project/files/;
     }

這個防盜連的目錄格式是這樣

https://your-domain/files/[MD5-HASH]/[Expire]/[File-Name]

 

長的像以下的網址

https://your-domain/files/Ajx8AXJA8AJDAS8ADD8A/123123123/your-file

而要產生防盜連的程式,以 PHP 為例子如下

<?php
$file_path = trim($file_path , '/'); // 你的檔案的相對路徑及檔名

$baseUrl = "http://your-domain/files";

$ttl = 300; // 過期時間五分鐘
$expires = time() + $ttl; // 過期時間
$secret = "hello";

$md5 = md5($expires . $file_path. " ". $secret , true); 
$hash = base64_encode($md5);
$hash = strtr($hash, '+/', '-_');
$hash = str_replace('=', '', $hash);

echo "{$baseUrl}/{$hash}/{$expires}/{$file_path}";

 

PHP 中的範例,會產生一個 300 秒過期的 LINK,Nginx 則是以 secure_link_md5  的定義來判斷雜湊是否正確。Nginx 官方上面的範例甚至可以做到用 $remote_addr (瀏覽者的 IP) 來防,如何定義更嚴謹複雜的判斷其實有很多方法。我試過 IP , Cookie 都可以在 Ngninx 中拿來做雜湊判斷,因此 PHP 也可以搭配 session 所使用的 cookie 來用更能保證給出的 Link 是只有該位使用者能下載的。

發表迴響