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 是只有該位使用者能下載的。