欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳解Angular開發(fā)中的登陸與身份驗證

 更新時間:2016年07月27日 10:47:16   投稿:daisy  
Angular是Google開發(fā)的一款瀏覽器端的高人氣JavaScript框架,Angular 經(jīng)常會被用到后臺和管理工具的開發(fā),這兩類都會需要對用戶進(jìn)行鑒權(quán)。而鑒權(quán)的第一步,就是進(jìn)行身份驗證。本文詳細(xì)介紹了Angular開發(fā)中的登陸與身份驗證。

前言

由于 Angular 是單頁應(yīng)用,會在一開始,就把大部分的資源加載到瀏覽器中,所以就更需要注意驗證的時機(jī),并保證只有通過了驗證的用戶才能看到對應(yīng)的界面。

本篇文章中的身份驗證,指的是如何確定用戶是否已經(jīng)登陸,并確保在每次與服務(wù)器的通信中,都能夠滿足服務(wù)器的驗證需求。注意,并不包括對具體是否具有某一個權(quán)限的判斷。

對于登陸,主要是接受用戶的用戶名密碼輸入,提交到服務(wù)器進(jìn)行驗證,處理驗證響應(yīng),在瀏覽器端構(gòu)建身份驗證數(shù)據(jù)。

實現(xiàn)身份驗證的兩種方式

目前,實現(xiàn)身份驗證的方法,主要有兩個大類:

Cookies

傳統(tǒng)的瀏覽器網(wǎng)頁,都是使用 Cookies 來驗證身份,實際上,瀏覽器端的應(yīng)用層里,基本不用去管身份驗證的事情,Cookies 的設(shè)置,由服務(wù)器端完成,在提交請求的時候,由瀏覽器自動附加對應(yīng)的 Cookies 信息,所以在 JavaScript 代碼中,不需要為此編寫專門的代碼。但每次請求的時候,都會帶上全部的 Cookies 數(shù)據(jù),

隨著 CDN 的應(yīng)用,移動端的逐漸興起, Cookies 越來越不能滿足復(fù)雜的、多域名下的身份驗證需求。

密鑰

實際上基于密鑰的身份驗證并不是最近才興起,它一直存在,甚至比 Cookies 歷史更長。當(dāng)瀏覽器在請求服務(wù)器的時候,將密鑰以特定的方式附加在請求中,比如放在請求的頭部( headers )。為此,需要編寫專門的客戶端代碼來管理。

最近出現(xiàn)的基于 JSON 的 Web 密鑰(JSON Web Token)標(biāo)準(zhǔn),便是典型的使用密鑰來實現(xiàn)的身份驗證。

在 Web 應(yīng)用中,如果是構(gòu)造 API ,則應(yīng)優(yōu)先考試使用密鑰方式。

處理登陸

登陸是身份驗證第一步,通過登陸,才能夠組織起來對應(yīng)的身份驗證數(shù)據(jù)。

需要使用單獨的登陸頁嗎?

登陸頁的處理,有兩種方式:

單獨的登陸頁,在登陸完成后,跳轉(zhuǎn)到單頁應(yīng)用之中,這樣做可以對單頁應(yīng)用的資源進(jìn)行訪問控制,防止非登陸用戶訪問,適合后臺或者管理工具的應(yīng)用場景。但實際上降低了單頁應(yīng)用的用戶體驗
在單頁應(yīng)用之內(nèi)執(zhí)行登陸,這樣更符合單頁應(yīng)用的設(shè)計理念,比較適合大眾產(chǎn)品的場景,因為惡意的人總是能夠拿到你單頁應(yīng)用的前端代碼

單獨的登陸頁

一般情況下,使用單獨的登陸頁的目的在于保護(hù)登陸后跳轉(zhuǎn)的頁面不被匿名用戶訪問。因此,在登陸頁里,構(gòu)造一個表單,直接采用傳統(tǒng)的表彰提交方式(非 Ajax),后端驗證用戶名密碼成功后,輸出登陸后單面應(yīng)用頁面的 HTML 。

在這種情況下,可以直接將身份驗證信息放在輸出的 HTML 里,比如,可以使用 Jade 構(gòu)造一個這樣的頁面:

<!-- dashboard.jade -->
doctype html
html
 head
  link(rel="stylesheet", href="/assets/app.e1c2c6ea9350869264da10de799dced1.css")
 body
  script.
   window.token = !{JSON.stringify(token)};
  div.md-padding(ui-view)
  script(src="/assets/app.84b1e53df1b4b23171da.js")


后端在用戶名密碼驗證成功之后,可以采用如下的方式來渲染輸出 HTML :

return res.render('dashboard', {
 token: token
});

Angular 應(yīng)用一啟動,便可以進(jìn)行需要使用身份驗證的通信。而且還保證了只有登陸成功的用戶才可以進(jìn)入這個頁面。

單頁應(yīng)用內(nèi)登陸的組織

對于多視圖的 Angular 應(yīng)用,一般會采用路由,在頁面之內(nèi),一般有固定的側(cè)邊欄菜單,或者頂部導(dǎo)航菜單,正文區(qū)域由路由模塊來控制。

下面的示例代碼,使用的是 Angular Material 來組織頁面,路由模塊使用的是 ui-router 。在應(yīng)用打開的時候,有專門的加載動畫,加載完成之后,顯示的頁面,使用 AppController 這個控制器,對于沒有登陸的用戶,會顯示登陸表單,登陸完成之后,頁面分為三大部分,一是頂部面包屑導(dǎo)航,二是側(cè)邊欄菜單,另外就是路由控制的正文部分

代碼如下:

<body ng-app="app" layout="row">
 <div id="loading">
  <!--頁面加載的提示-->
 </div>
 <div flex layout="row" ng-cloak ng-controller="AppController" ng-init="load()">
  <div ng-if="!isUserAuth", ng-controller="LoginController">
   <!--登陸表單-->
  </div>
  <div ng-if="isUserAuth" flex layout="row">
   <md-sidenav flex="15" md-is-locked-open="true" class="stop-text-select bbmd-sidebar md-whiteframe-4dp">
    <!--側(cè)邊欄菜單-->
   </md-sidenav>
   <md-content flex layout="column" role="main">
    <md-toolbar class="stop-text-select md-whiteframe-glow-z1">
     <!--頂部菜單-->
    </md-toolbar>
    <md-content>
     <!--路由-->
     <div ui-view class="md-padding"></div>
    </md-content>
   </md-content>
  </div>
 </div>
</body>

對于 Loading 動畫,是在 AppController 之外的,可以在 AppController 的代碼中,對其進(jìn)行隱藏。這樣達(dá)到了所有 CSS / JavaScript 加載完成之后 Loading 就消失的目的。

AppController 中有一個變量 isUserAuth ,初始化的時候是 false ,當(dāng)本地存儲的會話信息驗證有效,或者登陸完成之后,這個值便會置為 ture ,由于 ng-if 的控制,便可以實現(xiàn)隱藏登陸表單、顯示應(yīng)用內(nèi)容的目的。要注意,這里只有使用 ng-if 而不是 ng-show/ng-hide ,前者才會真正的刪除和增加 DOM 元素,而后者只是修改某個 DOM 元素的 CSS 屬性,這點很重要,只有這樣,才能夠保證登陸完成之后,再加載單頁應(yīng)用中的內(nèi)容,防止還沒有登陸,當(dāng)前路由中的控制器代碼就直接執(zhí)行了。

為什么客戶端也要加密密碼

一個比較理想的基于用戶名和密碼的登陸流程是這樣的:

    1.瀏覽器端獲取用戶輸入的密碼,使用 MD5 一類的哈希算法,生成固定長度的新密碼,如 md5(username + md5(md5(password))) ,再將密碼哈希值和用戶名提交給后端

    2.后端根據(jù)用戶名獲取對應(yīng)的鹽,使用用戶名和密碼哈希值,算出一個密文,根據(jù)用戶名和密文去數(shù)據(jù)庫查詢

    3.如果查詢成功,則生成密鑰,返回給瀏覽器,并執(zhí)行第 4 步

    4.后端生成新的鹽,根據(jù)新的鹽和瀏覽器提交的密碼哈希值,生成新的密文。在數(shù)據(jù)庫中更新鹽和密文

可能有 80% 的人無法理解為什么要把一個登陸做得這么復(fù)雜。這可能要寫一篇專門的文章才解釋得清楚。在這里先解釋一下為什么瀏覽器端要對密碼做哈希,原因如下:

    1.從源頭上保護(hù)用戶的密碼,保證只有做按鍵記錄才可以拿到用戶的原始密碼
    2.就算網(wǎng)絡(luò)被竊聽,又沒有使用 https ,那么被偷走的密碼,也只是哈希之后的,最多影響用戶在這個服務(wù)器里的數(shù)據(jù),而不影響使用相同密碼的其它網(wǎng)站
    3.就算是服務(wù)器的所有者,都無法獲取用戶的原始密碼
這種做法,使得用戶的最大風(fēng)險,也只是當(dāng)前這個應(yīng)用中的數(shù)據(jù)被竊取。不會擴(kuò)大損失范圍,絕不會出現(xiàn) CSDN 之流的問題。

登陸成功的通知

對于有些應(yīng)用,并不是所有的頁面都需要用戶登陸的,可能是進(jìn)行某些操作的時候,才需要登陸。在這種情況下,登陸完成之后,必須要通知整個應(yīng)用。這可以使用廣播這個功能。

簡易代碼如下:

angular
 .module('app')
 .controller('LoginController', ['$rootScope', LoginController]);

function LoginController($rootScope) {
 // 登陸成功之后調(diào)用的函數(shù)
 function afterLoginSuccess() {
  $rootScope.$broadcast('user.login.success', {
   // 需要傳輸?shù)臄?shù)據(jù)
  });
 }
}

在其它的控制器中,便可以監(jiān)聽這個廣播,并執(zhí)行登陸成功之后需要進(jìn)行的操作,如獲取列表或者詳情:

$scope.$on('user.login.success', function(handle, data){
 // 處理
});

身份驗證信息

登陸成功之后,服務(wù)器返回了密鑰,之后的 API 請求都需要帶上密鑰,而且請求返回的響應(yīng),還需要檢查是否是關(guān)于身份信息失效的錯誤。這一系列的工作比較繁瑣,應(yīng)該是自動完成才行。

保存

密鑰的保存,大概有如下幾個辦法:

    1.Cookies:前面已經(jīng)提到了,這個并不推薦使用。同時,它還有最大 4k 的限制

    2.sessionStorage:tab 頁內(nèi)有效,一旦關(guān)閉,或者打開了新的 tab 頁,sessionStorage 是不能共享的

    3.localStorage:較為理想的存儲方式,除非清理瀏覽器數(shù)據(jù),否則 localStorage 存儲的數(shù)據(jù)會一直存在

    4.Angular 單例 Service:存儲在應(yīng)用之內(nèi)得話,刷新后數(shù)據(jù)會丟失,當(dāng)然也不能 tab 頁之間共享
比較好的辦法是,身份驗證信息存儲在 localStorage 里,但在應(yīng)用啟動時,初始化到 Angular 的單例 Service 中。

在請求中加入身份驗證信息

身份驗證信息的目的,是為了向服務(wù)器表明身份,獲取數(shù)據(jù)。所以,在請求中需要附加身份驗證信息。

一般的應(yīng)用中,身份驗證信息都是放在請求的 headers 頭部中。如果在每次請求的時候,一一設(shè)置 headers ,那就太費時費力了。Angular 中的 $httpProvider 提供了一個攔截器 interceptors ,通過它可以實現(xiàn)對每一個請求和響應(yīng)的統(tǒng)一處理。

添加攔截器的方式如下:

angular
 .module('app')
 .config(['$httpProvider', function($httpProvider){
  $httpProvider.interceptors.push(HttpInterceptor);
 }]);

HttpInterceptor 的定義方式如下:

angular
 .module('app')
 .factory('HttpInterceptor', ['$q', HttpInterceptor]);

function HttpInterceptor($q) {
 return {
  // 請求發(fā)出之前,可以用于添加各種身份驗證信息
  request: function(config){
   if(localStorage.token) {
    config.headers.token = localStorage.token;
   }
   return config;
  },
  // 請求發(fā)出時出錯
  requestError: function(err){
   return $q.reject(err);
  },
  // 成功返回了響應(yīng)
  response: function(res){
   return res;
  },
  // 返回的響應(yīng)出錯,包括后端返回響應(yīng)時,設(shè)置了非 200 的 http 狀態(tài)碼
  responseError: function(err){
   return $q.reject(err);
  }
 };
}

攔截器提供了對發(fā)出請求到返回響應(yīng)的全生命周期處理,一般可以用來做下面幾個事情:

    1.統(tǒng)一在發(fā)出的請求中添加數(shù)據(jù),如添加身份驗證信息

    2.統(tǒng)一處理錯誤,包括請求發(fā)出時出的錯(如瀏覽器端的網(wǎng)絡(luò)不通),還有響應(yīng)時返回的錯誤

    3.統(tǒng)一處理響應(yīng),比如緩存一些數(shù)據(jù)等

    4.顯示請求進(jìn)度條

在上面的示例代碼中,當(dāng) localStorage 中包括 token 這個值時,就在每一個請求的頭部,添加一個 token 值。

失效及處理

一般的,后端應(yīng)該在 token 驗證失敗時,將響應(yīng)的 http 狀態(tài)碼設(shè)置為 401 ,這樣,在攔截器的 responseError 中便可以統(tǒng)一處理:

responseError: function(err){
 if(-1 === err.status) {
  // 遠(yuǎn)程服務(wù)器無響應(yīng)
 } else if(401 === err.status) {
  // 401 錯誤一般是用于身份驗證失敗,具體要看后端對身份驗證失敗時拋出的錯誤
 } else if(404 === err.status) {
  // 服務(wù)器返回了 404
 }
 return $q.reject(err);
}

總結(jié)

其實,只要服務(wù)器返回的狀態(tài)碼不是 200 ,都會調(diào)用 responseError ,可以在這里,統(tǒng)一處理并顯示錯誤。

以上內(nèi)容是關(guān)于Angular開發(fā)應(yīng)用中的登陸與身份驗證的相關(guān)知識,希望對大家學(xué)習(xí)Angular有所幫助。

相關(guān)文章

  • 淺析AngularJs HTTP響應(yīng)攔截器

    淺析AngularJs HTTP響應(yīng)攔截器

    這篇文章主要介紹了淺析AngularJs HTTP響應(yīng)攔截器的相關(guān)資料,需要的朋友可以參考下
    2015-12-12
  • 對Angular中單向數(shù)據(jù)流的深入理解

    對Angular中單向數(shù)據(jù)流的深入理解

    這篇文章主要給大家介紹了關(guān)于對Angular中單向數(shù)據(jù)流的深入理解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。
    2018-03-03
  • 詳解在 Angular 項目中添加 clean-blog 模板

    詳解在 Angular 項目中添加 clean-blog 模板

    本篇文章主要介紹了詳解在 Angular 項目中添加 clean-blog 模板,非常具有實用價值,需要的朋友可以參考下
    2017-07-07
  • 詳解用webpack2搭建angular2的項目

    詳解用webpack2搭建angular2的項目

    本篇文章主要介紹了詳解用webpack2搭建angular2的項目 ,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-06-06
  • Angularjs渲染的 using 指令的星級評分系統(tǒng)示例

    Angularjs渲染的 using 指令的星級評分系統(tǒng)示例

    本篇文章主要介紹了Angularjs渲染的 using 指令的星級評分系統(tǒng)示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-11-11
  • Angular6筆記之封裝http的示例代碼

    Angular6筆記之封裝http的示例代碼

    這篇文章主要介紹了Angular6筆記之封裝http的示例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-07-07
  • angular實現(xiàn)商品篩選功能

    angular實現(xiàn)商品篩選功能

    這篇文章主要為大家詳細(xì)介紹了angular實現(xiàn)商品篩選功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-02-02
  • 淺談Angular的$q, defer, promise

    淺談Angular的$q, defer, promise

    本文主要對Angular的 $q, defer, promise進(jìn)行實例分析介紹。具有很好的參考價值,需要的朋友一起來看下吧
    2016-12-12
  • 仿Angular Bootstrap TimePicker創(chuàng)建分鐘數(shù)-秒數(shù)的輸入控件

    仿Angular Bootstrap TimePicker創(chuàng)建分鐘數(shù)-秒數(shù)的輸入控件

    這篇文章主要為大家詳細(xì)介紹了仿Angular Bootstrap TimePicker創(chuàng)建分鐘數(shù)-秒數(shù)的輸入控件的相關(guān)資料,感興趣的小伙伴們可以參考一下
    2016-07-07
  • AngularJS實現(xiàn)Model緩存的方式

    AngularJS實現(xiàn)Model緩存的方式

    這篇文章主要介紹了AngularJS實現(xiàn)Model緩存的方式,分享了多種AngularJS實現(xiàn)Model緩存的方法,感興趣的小伙伴們可以參考一下
    2016-02-02

最新評論