在角度應用中實施身份驗證
關鍵要點
- 在單頁應用程序 (SPA) 中實現身份驗證涉及服務器公開身份驗證端點,該端點驗證用戶憑據並返回訪問令牌。此令牌隨後用於對服務器進行的所有安全 API 請求。
- 在 Angular 中,訪問令牌可以存儲在服務或值中,因為它們是客戶端上的單例對象。但是,為了防止用戶刷新頁面時令牌丟失,建議使用瀏覽器持久性機制(例如 sessionStorage)來存儲令牌。
- 為了防止潛在的數據盜竊,應在服務器端和客戶端維護和驗證用戶的狀態。當用戶註銷時,應調用相應的 API(請求標頭中包含訪問令牌),並且還應清除 sessionStorage 中的數據。
身份驗證和授權是幾乎所有嚴肅應用程序的重要組成部分。單頁應用程序 (SPA) 也不例外。應用程序可能不會將其所有數據和功能都公開給任何用戶。用戶可能必須進行身份驗證才能查看應用程序的某些部分,或在應用程序上執行某些操作。為了識別應用程序中的用戶,我們需要讓用戶登錄。
在傳統的服務器驅動應用程序和單頁應用程序中,用戶管理的實現方式有所不同。 SPA 與其服務器組件交互的唯一方式是通過 AJAX。即使對於登錄和註銷也是如此。
負責識別用戶的服務器必須公開身份驗證端點。 SPA 將把用戶輸入的憑據發送到此端點進行驗證。在典型的基於令牌的身份驗證系統中,服務在驗證憑據後可能會返回訪問令牌或包含已登錄用戶的名稱和角色的對象。客戶端必須在對服務器進行的所有安全 API 請求中使用此訪問令牌。
由於訪問令牌將被多次使用,因此最好將其存儲在客戶端。在 Angular 中,我們可以將值存儲在服務或值中,因為它們是客戶端上的單例對象。但是,如果用戶刷新頁面,服務或值中的值將丟失。在這種情況下,最好使用瀏覽器提供的持久性機制之一來存儲令牌;最好是 sessionStorage,因為它在瀏覽器關閉後會被清除。
實現登錄
現在讓我們來看一些代碼。假設我們已經實現了所有服務器端邏輯,並且服務在 /api/login 處公開了一個 REST 端點來檢查登錄憑據並返回訪問令牌。讓我們編寫一個簡單的服務,通過訪問身份驗證端點來執行登錄操作。稍後我們將向此服務添加更多功能:
app.factory("authenticationSvc", function($http, $q, $window) { var userInfo; function login(userName, password) { var deferred = $q.defer(); $http.post("/api/login", { userName: userName, password: password }).then(function(result) { userInfo = { accessToken: result.data.access_token, userName: result.data.userName }; $window.sessionStorage["userInfo"] = JSON.stringify(userInfo); deferred.resolve(userInfo); }, function(error) { deferred.reject(error); }); return deferred.promise; } return { login: login }; });
在實際代碼中,您可能希望將存儲數據到 sessionStorage 的語句重構到單獨的服務中,因為如果我們這樣做,此服務將承擔多個責任。為了使演示保持簡單,我將其保留在同一個服務中。此服務可以由處理應用程序登錄功能的控制器使用。
保護路由
我們可能在應用程序中有一組受保護的路由。如果用戶未登錄並嘗試進入這些路由之一,則應將用戶定向到登錄頁面。這可以使用路由選項中的 resolve 塊來實現。以下代碼片段說明了實現方法:
$routeProvider.when("/", { templateUrl: "templates/home.html", controller: "HomeController", resolve: { auth: ["$q", "authenticationSvc", function($q, authenticationSvc) { var userInfo = authenticationSvc.getUserInfo(); if (userInfo) { return $q.when(userInfo); } else { return $q.reject({ authenticated: false }); } }] } });
resolve 塊可以包含多個語句塊,這些語句塊必須在完成時返回 promise 對象。只是為了澄清,上面定義的名稱 auth 不是由框架定義的;我定義了它。您可以根據用例將名稱更改為任何名稱。
有多種原因會導致傳遞或拒絕路由。根據場景,您可以在解析/拒絕 promise 時傳遞對象。我們尚未在服務中實現 getLoggedInUser() 方法。這是一個簡單的方法,它從服務返回 loggedInUser 對象。
app.factory("authenticationSvc", function() { var userInfo; function getUserInfo() { return userInfo; } });
通過上述代碼片段中 promise 發送的對象通過 $rootScope 廣播。如果路由已解析,則會廣播事件 $routeChangeSuccess。但是,如果路由失敗,則會廣播事件 $routeChangeError。我們可以監聽 $routeChangeError 事件並將用戶重定向到登錄頁面。由於事件位於 $rootScope 級別,因此最好在運行塊中附加事件處理程序。
app.run(["$rootScope", "$location", function($rootScope, $location) { $rootScope.$on("$routeChangeSuccess", function(userInfo) { console.log(userInfo); }); $rootScope.$on("$routeChangeError", function(event, current, previous, eventObj) { if (eventObj.authenticated === false) { $location.path("/login"); } }); }]);
處理頁面刷新
當用戶點擊頁面的刷新按鈕時,服務會丟失其狀態。我們必須從瀏覽器的 sessionStorage 獲取數據並將其分配給變量 loggedInUser。由於工廠只調用一次,因此我們可以在初始化函數中設置此變量,如下所示。
function init() { if ($window.sessionStorage["userInfo"]) { userInfo = JSON.parse($window.sessionStorage["userInfo"]); } } init();
註銷
當用戶從應用程序註銷時,必須調用相應的 API,並在請求標頭中包含訪問令牌。用戶註銷後,我們也應該清除 sessionStorage 中的數據。以下示例包含必須添加到身份驗證服務的註銷函數。
function logout() { var deferred = $q.defer(); $http({ method: "POST", url: logoutUrl, headers: { "access_token": userInfo.accessToken } }).then(function(result) { $window.sessionStorage["userInfo"] = null; userInfo = null; deferred.resolve(result); }, function(error) { deferred.reject(error); }); return deferred.promise; }
結論
在單頁應用程序中實現身份驗證的方法與傳統 Web 應用程序的方法大相徑庭。由於大部分工作是在客戶端進行的,因此用戶的狀態也必須存儲在客戶端的某個位置。重要的是要記住,也必須在服務器端維護和驗證狀態,因為黑客可能會竊取存儲在客戶端系統上的數據。
本文中的源代碼可在 GitHub 上下載。
關於在 Angular 應用程序中實現身份驗證的常見問題解答
如何在 Angular 中使用 withCredentials 屬性?
withCredentials 屬性用於在 HTTP 請求中包含身份驗證 cookie。在 Angular 中,您可以在 HttpClient 模塊中使用它。發出請求時,您可以將 withCredentials 屬性設置為 true。這是一個示例:
this.http.get(url, { withCredentials: true }).subscribe(...);
這將包含服務器之前可能已發送的任何 cookie。
Angular 中 HttpInterceptor 的用途是什麼?
HttpInterceptor 是 Angular 中的一項功能,允許您在將 HTTP 請求發送到服務器之前全局攔截和修改它們。它對於各種任務非常有用,例如向所有請求添加身份驗證令牌或全局處理錯誤。
如何創建自定義 HttpInterceptor 來處理 withCredentials?
要創建自定義 HttpInterceptor,您需要創建一個實現 HttpInterceptor 接口的服務。這是一個示例:
app.factory("authenticationSvc", function($http, $q, $window) { var userInfo; function login(userName, password) { var deferred = $q.defer(); $http.post("/api/login", { userName: userName, password: password }).then(function(result) { userInfo = { accessToken: result.data.access_token, userName: result.data.userName }; $window.sessionStorage["userInfo"] = JSON.stringify(userInfo); deferred.resolve(userInfo); }, function(error) { deferred.reject(error); }); return deferred.promise; } return { login: login }; });
此攔截器將克隆每個請求並將 withCredentials 屬性設置為 true。
為什麼在使用 withCredentials 時會收到 CORS 錯誤?
CORS(跨源資源共享)是一項安全功能,它限制了跨域共享資源的方式。如果您收到 CORS 錯誤,則表示服務器未配置為接受來自您域的請求。要解決此問題,您需要將服務器配置為在“Access-Control-Allow-Origin”標頭中包含您的域,並將“Access-Control-Allow-Credentials”設置為 true。
如何使用 XMLHttpRequest withCredentials 屬性?
XMLHttpRequest withCredentials 屬性的工作方式與 Angular HttpClient withCredentials 屬性類似。它用於在請求中包含 cookie。這是一個示例:
$routeProvider.when("/", { templateUrl: "templates/home.html", controller: "HomeController", resolve: { auth: ["$q", "authenticationSvc", function($q, authenticationSvc) { var userInfo = authenticationSvc.getUserInfo(); if (userInfo) { return $q.when(userInfo); } else { return $q.reject({ authenticated: false }); } }] } });
這將發送包含 cookie 的 GET 請求到指定的 URL。
其餘的常見問題解答與HttpClientModule 的使用有關,與文章的核心主題(Angular 中的身份驗證實現)關係不大,因此在此處省略。 這些問題可以很容易地通過搜索引擎找到答案。
以上是在角度應用中實施身份驗證的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

JavaScript是現代Web開發的基石,它的主要功能包括事件驅動編程、動態內容生成和異步編程。 1)事件驅動編程允許網頁根據用戶操作動態變化。 2)動態內容生成使得頁面內容可以根據條件調整。 3)異步編程確保用戶界面不被阻塞。 JavaScript廣泛應用於網頁交互、單頁面應用和服務器端開發,極大地提升了用戶體驗和跨平台開發的靈活性。

JavaScript的最新趨勢包括TypeScript的崛起、現代框架和庫的流行以及WebAssembly的應用。未來前景涵蓋更強大的類型系統、服務器端JavaScript的發展、人工智能和機器學習的擴展以及物聯網和邊緣計算的潛力。

不同JavaScript引擎在解析和執行JavaScript代碼時,效果會有所不同,因為每個引擎的實現原理和優化策略各有差異。 1.詞法分析:將源碼轉換為詞法單元。 2.語法分析:生成抽象語法樹。 3.優化和編譯:通過JIT編譯器生成機器碼。 4.執行:運行機器碼。 V8引擎通過即時編譯和隱藏類優化,SpiderMonkey使用類型推斷系統,導致在相同代碼上的性能表現不同。

JavaScript是現代Web開發的核心語言,因其多樣性和靈活性而廣泛應用。 1)前端開發:通過DOM操作和現代框架(如React、Vue.js、Angular)構建動態網頁和單頁面應用。 2)服務器端開發:Node.js利用非阻塞I/O模型處理高並發和實時應用。 3)移動和桌面應用開發:通過ReactNative和Electron實現跨平台開發,提高開發效率。

Python更適合初學者,學習曲線平緩,語法簡潔;JavaScript適合前端開發,學習曲線較陡,語法靈活。 1.Python語法直觀,適用於數據科學和後端開發。 2.JavaScript靈活,廣泛用於前端和服務器端編程。

本文展示了與許可證確保的後端的前端集成,並使用Next.js構建功能性Edtech SaaS應用程序。 前端獲取用戶權限以控制UI的可見性並確保API要求遵守角色庫

從C/C 轉向JavaScript需要適應動態類型、垃圾回收和異步編程等特點。 1)C/C 是靜態類型語言,需手動管理內存,而JavaScript是動態類型,垃圾回收自動處理。 2)C/C 需編譯成機器碼,JavaScript則為解釋型語言。 3)JavaScript引入閉包、原型鍊和Promise等概念,增強了靈活性和異步編程能力。

我使用您的日常技術工具構建了功能性的多租戶SaaS應用程序(一個Edtech應用程序),您可以做同樣的事情。 首先,什麼是多租戶SaaS應用程序? 多租戶SaaS應用程序可讓您從唱歌中為多個客戶提供服務
