登陸信息 , 摘抄

 

enter image description here

在AngularJS應用中實現認證受權

在每個嚴肅的應用中,認證和受權都是很是重要的一個部分。單頁應用也不例外。應用並不會將全部的數據和功能都 暴露給全部的用戶。用戶須要經過認證和受權來查看應用的某個特定部分,或者在應用中進行特定的行爲。爲了在應用中對用戶進行識別,咱們須要讓用戶進行登陸。javascript

在用戶管理方面,傳統的服務器端應用和單頁應用的實現方式有所不一樣,單頁應用可以和服務器通訊的方式只有AJAX。對於登陸和退出來講也是如此。html

負責識別用戶的服務器端須要暴露出一個認證斷電。單頁應用將會把用戶輸入的信息發送到這個節點進行認證。在一個基於認證系統的典型token中,這項服務用於在認證完畢以後獲取一個token或者一個包含已登陸用戶的名字和角色信息的對象。客戶端則須要在全部的安全API中獲取這個token。java

因爲獲取toekn的行爲將會屢次發生,咱們最好將這個token存在客戶端。在Angular中,咱們能夠將這個值存在一個服務中,由於服務在客戶端中是一個單體。可是,若是用戶刷新了頁面,服務中的值將會丟失。在這種狀況下,最好將值存放在一個有瀏覽器提供的安全存儲中,在這裏咱們要是用的是sessionStorage,由於它在瀏覽器關閉時會自動被清空。web

實現登陸

咱們如今來看一些代碼。假設咱們已經實現了全部的服務器端的邏輯,而且有一個叫作api/login的REST接口進行登陸認證,它將返回一個token。咱們來寫一個簡單的服務用於用戶登陸。在後面咱們會爲這個服務逐漸添加功能:api

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 }; }); 

在實際的代碼中,你可能會想要將存儲的代碼重構爲一個單獨的服務。在這裏爲了簡單起見,咱們只是將它放在他用一個服務中。這個服務能夠被一個用於處理登陸功能的控制器所用。promise

安全路由

咱們須要在應用中設置一些安全路由。若是一個用戶沒有登陸同時想要進入到某一個安全路由中,他應該被重定向到登陸頁。咱們能夠使用路由選項中的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事件將會被廣播。然而,若是路由失敗,那麼事件$touteChangeError將會被廣播。咱們將監聽$routeChangeError事件並將用戶重定向到登陸頁上。因爲事件是在$rootScope層級上,最好在run函數中綁定事件處理器。session

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"); } }); }]); 

處理頁面刷新

當用戶刷新頁面時,服務將會失去現有狀態。咱們須要從瀏覽器的session storage中獲取數據並將這些值賦值給loggerInUser變量。因爲一個factory只會被調用一次,咱們須要在一個初始化函數中設置這個變量,代碼以下所示:

function init() { if ($window.sessionStorage["userInfo"]) { userInfo = JSON.parse($window.sessionStorage["userInfo"]); } } init(); 

退出

當用戶想要從應用中退出時,相應的API必須連同包含在請求頭部中的token一塊兒被調用。一旦用戶退出,咱們還須要清空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應用的認證方式很是不一樣。因爲主要的工做都搬到了瀏覽器端,用戶的狀態也須要存儲在客戶端。重要的一點是要記住用戶的狀態也須要的服務器端保存和進行驗證,由於駭客極可能慧聰客戶端竊取用戶的數據。


本文譯自Implementing Authentication in Angular Applications,原文地址http://www.sitepoint.com/implementing-authentication-angular-applications/

相關文章
相關標籤/搜索