javascript - Angular:僅在授權(使用 JWT)時從伺服器加載懶加載模組
我在我的 Angular 應用程式中使用延遲加載模組,到目前為止一切運作正常。
現在我有一個關於安全性方面的具體問題,但我還沒有找到答案。你有機會使用 Angular Guard 和 "CanLoad" 來對懶加載的模組進行 "保護"。但是這僅僅是在前端,因此它可能被繞過,即使用戶不被允許查看該模組,它仍然會被加載。例如管理區域。
我正在使用 JWT 進行授權,所有資料都託管在與承載 Angular 應用程式的應用伺服器完全分離的 Azure 後端。
我現在正在考慮是否有任何方法可以使用 JWT 來驗證並檢查當前模組是否被允許由該用戶在伺服器端加載。
所以例如你有以下模組:
- 功能A
- 功能B
- 功能C
- 管理員
在每個功能模組/區域的 JWT 中,payload 裡都有一個變數,用來表示使用者是否被允許使用此功能(true/false)。
現在如果使用者嘗試載入功能 A 的延遲加載模組,我想在應用程式伺服器上使用公鑰驗證 JWT,以知道「這個金鑰是有效的,並且確實是由 Azure 伺服器那樣簽署的」。
接下來它會檢查 FeatureA 的變量是否設置為 true。如果是,我將把模組(js-chunk 文件)返回給客戶端。如果不是,我將返回 403 禁止訪問。
所以即使應用程式被修改,只有當該使用者擁有一個聲明此功能已對其啟用的有效 JWT 時,該人才能獲得功能模組。
有沒有辦法做到這個呢?我不知道應該從哪裡開始尋找解決方案。所以如果有人能告訴我如何獲得它以及我需要什麼,我將非常感激!
提前感謝。
答案#1
解決方案
這完全取決於你的後端。
由於 Angular 前端文件只是由某些伺服器提供的靜態文件,因此這取決於是否:
- 你可以區分模組的檔案
- 應用程式提供前端檔案服務時,可以根據某種身份驗證/授權來允許或阻止對選定檔案的訪問
廣告 1
這對 Angular 沒有任何問題。你必須使用以下標誌來構建你的專案[1]:
ng (...) --named-chunks=true (...)
這將產生具有以下名稱的模塊 js 文件:
your-module.<hashNumber>.js
廣告 2 - Spring Boot 解決方案
在我目前的專案中,我們使用 (Java) Spring Boot 來提供應用程式的前端和後端。我們使用 spring-security 登入表單登入應用程式。它會創建會話並在 cookies 中保持對該會話的追蹤。每次請求時 cookie 都會被傳送到後端——包括在載入 lazy 模組時。在後端,你將會話與使用者角色關聯。這讓你可以根據使用者是否已登入並擁有適當的角色來允許其下載 Angular 模組。
<security:intercept-url pattern="/your-module.*.js" access="hasAnyRole('SOME_ROLE')"/>
廣告 2 - 雲端 (AWS)
由於我對 Azure 不熟悉,但我對 AWS 有一些背景,我可能會嘗試描述一些基於 AWS 的解決方案,這些解決方案應該可以移植到所有主要的雲端供應商。
如果您正在使用雲端服務提供商的身份驗證和授權系統(例如 AWS Cognito),那麼您應該能夠保護對以下資源的訪問:
a) 儲存(如 S3)或
b) 在虛擬機(如 EC2)上提供的應用程式。
在第一種情況 (a) 中,您可能能夠根據某種類型的 policies(資源存取限制器)和 authentication system groups(例如來自 Cognito 的群組)設置存取選定模組(JavaScript 文件)的策略。
在第二種情況 (b) 中,這取決於你的後端。簡短的 Spring Boot 解決方案如上所述。
你為什麼需要保護你的模組?
最好的做法是不要將任何脆弱的代碼部分放在前端應用程序中,但即便如此,你的代碼中仍可能包含某些信息,這些信息可能被用來進一步發起攻擊(例如社會工程攻擊)。因此,一般來說,最好盡可能縮小權限,並允許用戶僅擁有他們所需的最少權限。
來源
[1] https://angular.io/cli/build
答案#2
... 又有另一個開發者為另一輛戰車發明另一個輪子...
首先,懶加載的模組是由 Webpack 的 jsonp 函數接收的(如果我們談論的是 Angular CLI,它在內部使用 Webpack),默認情況下這個函數只是將另一個腳本注入到頁面中;這意味著你幾乎沒有機會通過這個請求傳遞你的令牌,因為它是以腳本形式加載的,而不是 XHR。將令牌作為 GET 參數也是一個安全問題,所以我認為這也不是一個選項(即使這是可行的)。
假設你可以改變 Webpack 載入區塊的方式(或例如,編寫一個自訂的服務工作者來做你想做的事情,我仍然不確定這是否可以輕鬆完成)。那麼我們就來到了這個問題:
為什麼你需要保護管理員(或其他)模組?
這只是一段程式碼。如果你在這個模組中有敏感資訊,那就是你的架構問題。所有敏感資料都應該來自 API。
你唯一需要保護的是從你的應用程式使用的管理 API。每個呼叫都應該根據該呼叫提供的令牌進行驗證。如果用戶在令牌中具有適當的 scope(或你用來授權的任何方式),那麼請求應該返回數據,否則返回 403。就是這麼簡單。
