善用SAS機制在網頁上安全的分享媒體內容

最近爬蟲事件很熱鬧,許多網站針對防止爬蟲程式竊取資料都有著不同的做法。日前,在一個聚餐中,有位同學提到了一個她們自己公司最近的需求。

該公司所開發的網站,需要將大量的媒體內容(影片、圖片、或是文件),分享給不特定的用戶,上網觀看這些內容的用戶不需要登入,就可以以匿名方式檢視這些媒體內容。

然而,該網站又不希望,用戶(其實主要擔心的不是用戶,是爬蟲)能夠輕易地獲取媒體的網址,就將其分享給其他人,甚至輕易複製出一個完全一模一樣的網站。

簡單的說就是,網站想分享資訊,卻不希望用戶可以再次把這資訊分享給其他人,問大家有沒有好方法。

問到我,當然推一下 Azure 的 Blob儲存體。
近代的雲端儲存機制,其實都有提供類似的功能,可以讓媒體(mp4, jepg, pdf, … etc.)的檢視網址,變成僅供一次性的使用,而且可以針對特定IP或特定時間進行鎖定。

也就是說,當用戶進到某個網頁觀看上面的影片、圖片、閱讀PDF文件的時候,倘若將該媒體的網址複製下來,然後傳給其他第三人,這個第三人是無法用該網址觀看媒體資料的,因為IP不同,觀看的時間也不同。

這個功能稱為 SAS( Shared Access Signature ) :
圖片

在 Azure Storage 儲存體的 Blob 上,你可以針對一個受保護的檔案,設定其 SAS( Shared Access Signature ),這意味著如果用戶拿到這個檔案的 url,也無法開啟,一定要有一個合法的簽章,類似底下這樣:
https://teststo202508.blob.core.windows.net/testcontainer/sashimi.jpg?sp=r&st=2025-08-02T07:10:29Z&se=2025-08-02T15:25:29Z&spr=https&sv=2024-11-04&sr=b&sig=ch7GZYS8rJii%2B45GJb4kKWj4valFW84E3Btgppc51aE%3D

如果用戶只拿該檔案的原始URL:
https://teststo202508.blob.core.windows.net/testcontainer/sashimi.jpg
肯定是不能讀取的,會出現底下錯誤:
圖片

你可以針對該檔案,依照你想公開的對象、時間、或權限,生成該檔案的SAS:
圖片

設定完成之後,會產生一個唯一且會過期的 URL,這樣用戶(或爬蟲)即便取得該URL,分享給其他人(或使用在自己網站上)也無法顯示該媒體的內容了。

當然,這一個生成SAS簽章的動作,必須是動態由程式碼進行的(而非像是上面展示的,使用 Azure Portal 由手動產生),網站的後端程式碼可以在取得當前用戶所在的IP位置之後,在每一個頁面上動態的生成僅限該用戶才能存取且有時間限制的URL,程式碼類似底下這樣:

//create SAS
SharedAccessBlobPolicy sasConstraints = new SharedAccessBlobPolicy();
sasConstraints.SharedAccessStartTime = DateTimeOffset.UtcNow.AddMinutes(-5);
sasConstraints.SharedAccessExpiryTime = DateTimeOffset.UtcNow.AddHours(1);
sasConstraints.Permissions = SharedAccessBlobPermissions.Read | SharedAccessBlobPermissions.Write;
var sasBlobToken = cloudBlockBlob.GetSharedAccessSignature(sasConstraints);
Console.WriteLine($"\r\nSAS url: {cloudBlockBlob.Uri + sasBlobToken}");
Console.WriteLine("Press 'Enter' to continue.");
Console.ReadLine();

一般來說,在比較嚴謹的情況下,媒體連結的URL有效期限,可以設定在5-10分鐘以內,差不多就是一個網頁被用戶檢視的最長時間,如此一來,每一次用戶檢視網頁的時候,網頁上的媒體都有著唯一的URL,該URL僅針對該用戶(的IP)以及網頁檢視時間開放,若是用戶(或爬蟲)將該URL複製給其他人,也無法輕易檢視或下載檔案。

如此可以用最輕鬆的方式達成基本的媒體保護,雖然無法完全防止資料被下載(因為檢視本身就是一種下載),但針對爬蟲大量的抓取網址,就能夠做到有效的基本防護。

留言

這個網誌中的熱門文章

使用LM Studio輕鬆在本地端以API呼叫大語言模型(LLM)

開啟 teams 中的『會議轉錄(謄寫)』與Copilot會議記錄、摘要功能

原來使用 .net 寫個 MCP Server 如此簡單

原來使用 .net 寫個 MCP Client 也如此簡單

使用 Dify API 快速建立一個包含前後文記憶的對談機器人