Node.js 入门详解(四)
數(shù)據(jù)庫與身份認(rèn)證
- 1. 數(shù)據(jù)庫的基本概念
- 1.1 什么是數(shù)據(jù)庫
- 1.2 常見的數(shù)據(jù)庫及分類
- 1.3 傳統(tǒng)型數(shù)據(jù)庫的數(shù)據(jù)組織結(jié)構(gòu)
- 1.3.1 Excel的數(shù)據(jù)組織結(jié)構(gòu)
- 1.3.2 傳統(tǒng)型數(shù)據(jù)庫的數(shù)據(jù)組織結(jié)構(gòu)
- 1.3.3 實際開發(fā)中庫、表、行、字段的關(guān)系
- 2. 安裝并配置MySQL
- 2.1 了解需要安裝哪些 MySQL 相關(guān)的軟件
- 2.2 MySQL在 Mac 環(huán)境下的安裝
- 2.3 MySQL在 Windows 環(huán)境下的安裝
- 3. MySQL的基本使用
- 3.1 使用 MySQL Workbench 管理數(shù)據(jù)庫
- 3.1.1連接數(shù)據(jù)庫
- 3.1.2 MySQL主界面的組成
- 3.1.3 創(chuàng)建數(shù)據(jù)庫
- 3.1.4 創(chuàng)建數(shù)據(jù)表
- DataType 數(shù)據(jù)類型:
- 字段的特殊標(biāo)識:
- 3.1.5 向表中寫入數(shù)據(jù)
- 3.2 使用 SQL 管理數(shù)據(jù)庫
- 3.2.1 什么是 SQL
- 3.2.2 SQL能做什么
- 3.2.3 SQL學(xué)習(xí)目標(biāo)
- 3.3 SQL的 SELECT 語句
- 3.3.1 語法
- 3.3.2 SELECT * 示例
- 3.3.3 SELECT 列名稱 示例
- 3.4 SQL 的 INSERT INTO 語句
- 3.4.1 語法
- 3.4.2 INSERT INTO 示例
- 3.5 SQL 的 UPDATE 語句
- 3.5.1 語法
- 3.5.2 2. UPDATE示例:更新某一行中的一個列
- 3.5.3 3. UPDATE示例 - 更新某一行中的若干列
- 3.6 SQL 的 DELETE 語句
- 3.6.1 語法
- 3.6.2 2. DELETE示例
- 3.7 SQL 的 WHERE 子句
- 3.7.1 語法
- 3.7.2 可在 WHERE 子句中使用的運算符
- 3.7.3 WHERE子句示例
- 3.8 SQL的 AND 和 OR 運算符
- 3.8.1 語法
- 3.8.2 運算符示例
- 3.8.2.1 AND 運算符
- 3.8.2.2 OR運算符
- 3.9 SQL 的 ORDER BY 子句
- 3.9.1 語法
- 3.9.2 ORDER BY子句- 升序排序
- 3.9.3 ORDER BY 子句-降序排序
- 3.9.4 4. ORDER BY子句-多重排序
- 3.10 SQL 的 COUNT(*) 函數(shù)
- 3.10.1 語法
- 3.10.2 COUNT(*)示例
- 3.10.3 使用 as 為列設(shè)置別名
- 4. 在項目中操作 MySQL
- 4.1 在項目中操作數(shù)據(jù)庫的步驟
- 4.2 安裝與配置 mysql 模塊
- 4.2.1 安裝 mysql 模塊
- 4.2.2 配置 mysql 模塊
- 4.2.3 測試 mysql 模塊能否正常工作
- 4.3使用 mysql 模塊操作 MySQL 數(shù)據(jù)庫
- 4.3.1 查詢數(shù)據(jù)
- 4.3.2 插入數(shù)據(jù)
- 4.3.3 插入數(shù)據(jù)的便捷方式
- 4.3.4 更新數(shù)據(jù)
- 4.3.5 更新數(shù)據(jù)的便捷方式
- 4.3.6 刪除數(shù)據(jù)
- 4.3.7 標(biāo)記刪除
- 5. 前后端的身份認(rèn)證
- 5.1 Web開發(fā)模式
- 5.1.1 服務(wù)端渲染的Web開發(fā)模式
- 5.1.2 服務(wù)端渲染的優(yōu)缺點
- 5.1.3 前后端分離 的 Web 開發(fā)模式
- 5.1.4 前后端分離的優(yōu)缺點
- 5.1.5 如何選擇 Web 開發(fā)模式
- 5.2 身份認(rèn)證
- 5.2.1 什么是 身份認(rèn)證
- 5.2.2 為什么需要身份認(rèn)證
- 5.2.3 不同開發(fā)模式下的 身份認(rèn)證
- 5.3 Session 認(rèn)證機(jī)制
- 5.3.1 HTTP協(xié)議的無狀態(tài)性
- 5.3.2 如何突破 HTTP 無狀態(tài)的限制
- 5.3.3 什么是 Cookie
- 5.3.4 Cookie 在身份認(rèn)證中的作用
- 5.3.5 Cookie不具有安全性
- 5.3.6 提高 身份認(rèn)證的 安全性
- 5.3.7 Session 的工作原理
- 5.4 在 Express 中使用 Session 認(rèn)證
- 5.4.1 安裝express-session中間件
- 5.4.2 配置express-session中間件
- 5.4.3 向 session 中存數(shù)據(jù)
- 5.4.4 從 session 中取數(shù)據(jù)
- 5.4.5 清空 session
- 5.5 JWT認(rèn)證機(jī)制
- 5.5.1 了解 Session 認(rèn)證的局限性
- 5.5.2 什么是 JWT
- 5.5.3 JWT的工作原理
- 5.5.4 4. JWT的組成部分
- 5.5.5 JWT的三個部分各自代表的含義
- 5.5.6 JWT的使用方式
- 5.6 在 Express 中使用 JWT
- 5.6.1 安裝JWT相關(guān)的包
- 5.6.2 導(dǎo)入 JWT 相關(guān)的包
- 5.6.3 定義 secret 密鑰
- 5.6.4 在登錄成功后生成 JWT 字符串
- 5.6.5 將 JWT 字符串 還原為 JSON 對象
- 5.6.6 使用 req.user 獲取用戶信息
- 5.6.7 捕獲解析 JWT 失敗后產(chǎn)生的錯誤
1. 數(shù)據(jù)庫的基本概念
1.1 什么是數(shù)據(jù)庫
數(shù)據(jù)庫(database )是用來 組織 、 存儲 和 管理 數(shù)據(jù)的倉庫。當(dāng)今世界是一個充滿著數(shù)據(jù)的互聯(lián)網(wǎng)世界,充斥著大量的數(shù)據(jù) 。 數(shù)據(jù)的來源 有很多,比如出行記錄、消費記錄、瀏覽的網(wǎng)頁、發(fā)送的消息等等。除了文本類型的數(shù)據(jù),圖像、音樂、聲音都是數(shù)據(jù)。
為了方便管理互聯(lián)網(wǎng)世界中的數(shù)據(jù),就有了數(shù)據(jù)庫管理系統(tǒng) 的概念(簡稱:數(shù)據(jù)庫)。用戶可以對數(shù)據(jù)庫中的數(shù)據(jù)進(jìn)行 新增 、 查詢 、 更新 、 刪除 等操作。
1.2 常見的數(shù)據(jù)庫及分類
市面上的數(shù)據(jù)庫有很多種,最常見的數(shù)據(jù)庫有如下幾個:
- MySQL 數(shù)據(jù)庫(目前 使用最廣泛 、 流行度最高 的開源免費數(shù)據(jù)庫;Community + Enterprise
- Oracle 數(shù)據(jù)庫(收費)
- SQL Server 數(shù)據(jù)庫(收費)
- Mongodb 數(shù)據(jù)庫( Community + Enterprise)
其中,MySQL 、 Oracle 、 SQL Server 屬于 傳統(tǒng)型數(shù)據(jù)庫 (又叫做 關(guān)系型數(shù)據(jù)庫 或 SQL 數(shù)據(jù)庫 ),這三者的設(shè)計理念相同,用法比較類似。
而Mongodb 屬于 新型數(shù)據(jù)庫 (又叫做 非關(guān)系型數(shù)據(jù)庫 或 NoSQL 數(shù)據(jù)庫 ),它在一定程度上彌補了傳統(tǒng)型數(shù)據(jù)庫的缺陷。
1.3 傳統(tǒng)型數(shù)據(jù)庫的數(shù)據(jù)組織結(jié)構(gòu)
數(shù)據(jù)的組織結(jié)構(gòu):指的就是數(shù)據(jù)以什么樣的結(jié)構(gòu)進(jìn)行存儲。
傳統(tǒng)型數(shù)據(jù)庫的數(shù)據(jù)組織結(jié)構(gòu),與Excel 中數(shù)據(jù)的組織結(jié)構(gòu)比較類似。
因此,我們可以對比著Excel 來了解和學(xué)習(xí)傳統(tǒng)型數(shù)據(jù)庫的數(shù)據(jù)組織結(jié)構(gòu)。
1.3.1 Excel的數(shù)據(jù)組織結(jié)構(gòu)
每個Excel 中,數(shù)據(jù)的組織結(jié)構(gòu)分別為 工作簿 、工作表 、數(shù)據(jù)行 、列 四大部分組成。
1.3.2 傳統(tǒng)型數(shù)據(jù)庫的數(shù)據(jù)組織結(jié)構(gòu)
在傳統(tǒng)型數(shù)據(jù)庫中,數(shù)據(jù)的組織結(jié)構(gòu)分為數(shù)據(jù)庫 ( database)、 數(shù)據(jù)表 ( table)、 數(shù)據(jù)行 ( row)、 字段 ( field)這 4 大部分組成。
1.3.3 實際開發(fā)中庫、表、行、字段的關(guān)系
2. 安裝并配置MySQL
2.1 了解需要安裝哪些 MySQL 相關(guān)的軟件
對于開發(fā)人員來說,只需要安裝 MySQL Server 和 MySQL Workbench 這兩個軟件,就能滿足開發(fā)的需要了。
- MySQL Server:專門用來提供數(shù)據(jù)存儲和服務(wù)的軟件 。
- MySQL Workbench:可視化的 MySQL 管理工具 ,通過它,可以方便的操作存儲在 MySQL Server 中的數(shù)據(jù)。
2.2 MySQL在 Mac 環(huán)境下的安裝
在Mac 環(huán)境下安裝 MySQL 的過程比 Windows 環(huán)境下的步驟簡單很多:
具體的安裝教程,可以參考《MySQL在Mac環(huán)境下的安裝》=> 點擊前往
2.3 MySQL在 Windows 環(huán)境下的安裝
在Windows 環(huán)境下安裝 MySQL ,只需要運行 mysql installer community 8.0.19.0.msi 這個安裝包,就能一次性將 MySQL Server 和 MySQL Workbench 安裝到自己的電腦上。
具體的安裝教程,可以參考 《MySQL在 Windows 環(huán)境下的安裝》=> 點擊前往
3. MySQL的基本使用
3.1 使用 MySQL Workbench 管理數(shù)據(jù)庫
3.1.1連接數(shù)據(jù)庫
3.1.2 MySQL主界面的組成
3.1.3 創(chuàng)建數(shù)據(jù)庫
3.1.4 創(chuàng)建數(shù)據(jù)表
DataType 數(shù)據(jù)類型:
① int 整數(shù) ② varchar len ) 字符串 ③ tinyint 1 ) 布爾值字段的特殊標(biāo)識:
① PK Primary Key 主鍵、唯一標(biāo)識 ② NN Not Null 值不允許為空 ③ UQ Unique 值唯一 ④ AI Auto Increment 值自動增長3.1.5 向表中寫入數(shù)據(jù)
3.2 使用 SQL 管理數(shù)據(jù)庫
3.2.1 什么是 SQL
SQL(英文全稱 Structured Query Language )是 結(jié)構(gòu)化查詢語言 ,專門用來 訪問和處理數(shù)據(jù)庫 的編程語言。能夠讓我們 以編程的形式,操作數(shù)據(jù)庫里面的數(shù)據(jù) 。
三個關(guān)鍵點:
3.2.2 SQL能做什么
3.2.3 SQL學(xué)習(xí)目標(biāo)
重點掌握如何使用 SQL 從數(shù)據(jù)表中:
查詢數(shù)據(jù)(select)、 插入數(shù)據(jù)(insert into)、 更新數(shù)據(jù)(update)、 刪除數(shù)據(jù)(delete)。
額外需要掌握的 4 種 SQL 語法:
where條件 、 and 和 or 運算符 、 order by 排序 、 count(*) 函數(shù)
3.3 SQL的 SELECT 語句
3.3.1 語法
SELECT語句用于 從表中查詢數(shù)據(jù) 。執(zhí)行的結(jié)果被存儲在一個 結(jié)果表 中(稱為 結(jié)果集 )。語法格式如下:
🔔 注: SQL 語句中的 關(guān)鍵字 對 大小寫不敏感 。 SELECT 等效于 select FROM 等效于 from 。
3.3.2 SELECT * 示例
我們希望從 users 表中選取所有的列,可以使用 符號 * 取代列的名稱,示例如下:
3.3.3 SELECT 列名稱 示例
如需獲取名為 "username " 和 "password " 的列的內(nèi)容(從名為 “users” 的數(shù)據(jù)庫表),請使用下面的 SELECT 語句:
3.4 SQL 的 INSERT INTO 語句
3.4.1 語法
INSERT INTO 語句用于 向數(shù)據(jù)表中 插入新的數(shù)據(jù)行 ,語法格式如下:
3.4.2 INSERT INTO 示例
向 users 表中,插入一條 username 為 tony stark password 為 098123 的用戶數(shù)據(jù),示例如下:
3.5 SQL 的 UPDATE 語句
3.5.1 語法
Update 語句用于 修改表中的數(shù)據(jù) 。語法格式如下:
3.5.2 2. UPDATE示例:更新某一行中的一個列
把 users 表中 id 為 7 的用戶密碼,更新為 888888 。示例如下:
3.5.3 3. UPDATE示例 - 更新某一行中的若干列
把 users 表中 id 為 2 的 用戶密碼 和 用戶狀態(tài) ,分別更新為 admin123 和 1 。示例如下:
3.6 SQL 的 DELETE 語句
3.6.1 語法
DELETE 語句用于刪除表中的行。語法格式如下:
3.6.2 2. DELETE示例
從 users 表中,刪除 id 為 4 的用戶,示例如下:
3.7 SQL 的 WHERE 子句
3.7.1 語法
WHERE 子句 用于 限定選擇的標(biāo)準(zhǔn) 。在 SELECT、UPDATE、DELETE 語句中, 皆可使用 WHERE 子句來限定選擇的標(biāo)準(zhǔn)。
3.7.2 可在 WHERE 子句中使用的運算符
下面的運算符可在 WHERE 子句中使用,用來限定選擇的標(biāo)準(zhǔn):
| = | 等于 |
| <> | 不等于 |
| > | 大于 |
| < | 小于 |
| >= | 大于等于 |
| <= | 小于等于 |
| BETWEEN | 在某個范圍內(nèi) |
| LIKE | 搜索某種模式 |
🔔 注: 在某些版本的SQL 中,操作符 <> 可以寫為 !=
3.7.3 WHERE子句示例
可以通過 WHERE 子句來限定 SELECT 的查詢條件:
3.8 SQL的 AND 和 OR 運算符
3.8.1 語法
AND 和 OR 可 在 WHERE 子語句 中 把兩個或多個條件結(jié)合起來 。
AND 表示 必須同時滿足多個條件 ,相當(dāng)于 JavaScript 中的 && 運算符,例如 if (a !== 10 && a !== 20);
OR 表示 只要滿足任意一個條件即可 ,相當(dāng)于 JavaScript 中的 || 運算符,例如 if(a !== 10 || a !== 20)
3.8.2 運算符示例
3.8.2.1 AND 運算符
使用 AND 來顯示所有 status = 0,并且 id < 3 的用戶:
3.8.2.2 OR運算符
使用 OR 來顯示所有status = 1,或者 username = 'zs' 的用戶:
3.9 SQL 的 ORDER BY 子句
3.9.1 語法
ORDER BY 語句用于 根據(jù)指定的列 對結(jié)果集進(jìn)行排序 。
ORDER BY 語句 默認(rèn) 按照 升序 對記錄進(jìn)行排序。
如果您希望按照 降序 對記錄進(jìn)行排序,可以使用 DESC 關(guān)鍵字。
3.9.2 ORDER BY子句- 升序排序
對users 表中的數(shù)據(jù),按照 status 字段進(jìn)行升序排序,示例如下:
3.9.3 ORDER BY 子句-降序排序
對 users 表中的數(shù)據(jù),按照 id 字段進(jìn)行降序排序,示例如下:
3.9.4 4. ORDER BY子句-多重排序
對 users 表中的數(shù)據(jù),先按照 status 字段進(jìn)行 降序排序 ,再按照 username 的 字母順序 ,進(jìn)行 升序排序 ,示例如下:
3.10 SQL 的 COUNT(*) 函數(shù)
3.10.1 語法
COUNT(*) 函數(shù)用于返回 查詢結(jié)果 的 總數(shù)據(jù)條數(shù) ,語法格式如下:
3.10.2 COUNT(*)示例
查詢 users 表中 status 為 0 的總數(shù)據(jù)條數(shù):
3.10.3 使用 as 為列設(shè)置別名
如果希望給查詢出來的列名稱設(shè)置別名,可以使用 AS 關(guān)鍵字,示例如下:
4. 在項目中操作 MySQL
4.1 在項目中操作數(shù)據(jù)庫的步驟
4.2 安裝與配置 mysql 模塊
4.2.1 安裝 mysql 模塊
mysql 模塊是托管于 npm 上的 第三方模塊 。它提供了在 Node.js 項目中 連接 和 操作 MySQL 數(shù)據(jù)庫的能力。
要在項目中使用它,需要先運行如下命令,將mysql 安裝為項目的依賴包:
4.2.2 配置 mysql 模塊
在使用 mysql 模塊操作 MySQL 數(shù)據(jù)庫之前, 必須先對 mysql 模塊進(jìn)行必要的配置 ,主要的配置步驟如下:
4.2.3 測試 mysql 模塊能否正常工作
調(diào)用 db.query () 函數(shù),指定要執(zhí)行的 SQL 語句,通過回調(diào)函數(shù)拿到執(zhí)行的結(jié)果:
4.3使用 mysql 模塊操作 MySQL 數(shù)據(jù)庫
4.3.1 查詢數(shù)據(jù)
查詢 users 表中所有的數(shù)據(jù):
4.3.2 插入數(shù)據(jù)
向 users 表中新增數(shù)據(jù), 其中 username 為 Spider-Man password 為 pcc321 。示例代碼如下:
4.3.3 插入數(shù)據(jù)的便捷方式
向表中新增數(shù)據(jù)時,如果 數(shù)據(jù)對象的每個屬性 和 數(shù)據(jù)表的字段 一 一對應(yīng) ,則可以通過如下方式快速插入數(shù)據(jù):
4.3.4 更新數(shù)據(jù)
可以通過如下方式,更新表中的數(shù)據(jù):
4.3.5 更新數(shù)據(jù)的便捷方式
更新表數(shù)據(jù)時,如果 數(shù)據(jù)對象的每個屬性 和 數(shù)據(jù)表的字段 一 一對應(yīng) ,則可以通過如下方式快速更新表數(shù)據(jù):
4.3.6 刪除數(shù)據(jù)
在刪除數(shù)據(jù)時,推薦根據(jù) id 這樣的唯一標(biāo)識,來刪除對應(yīng)的數(shù)據(jù)。示例如下:
4.3.7 標(biāo)記刪除
使用 DELETE 語句,會把真正的把數(shù)據(jù)從表中刪除掉。為了保險起見, 推薦使用 標(biāo)記刪除 的形式,來模擬刪除的動作 。
所謂的標(biāo)記刪除,就是在表中設(shè)置類似于 status 這樣的狀態(tài)字段,來 標(biāo)記 當(dāng)前這條數(shù)據(jù)是否被刪除。
當(dāng)用戶執(zhí)行了刪除的動作時,我們并沒有執(zhí)行DELETE 語句把數(shù)據(jù)刪除掉,而是執(zhí)行了 UPDATE 語句,將這條數(shù)據(jù)對應(yīng)的 status 字段標(biāo)記為刪除即可。
5. 前后端的身份認(rèn)證
5.1 Web開發(fā)模式
目前主流的 Web 開發(fā)模式有兩種,分別是:
5.1.1 服務(wù)端渲染的Web開發(fā)模式
服務(wù)端渲染的概念:服務(wù)器 發(fā)送給客戶端的 HTML 頁面 ,是 在服務(wù)器通過字符串的拼接,動態(tài)生成的 。因此,客戶端不需要使用 Ajax 這樣的技術(shù)額外請求頁面的數(shù)據(jù)。代碼示例如下:
5.1.2 服務(wù)端渲染的優(yōu)缺點
優(yōu)點:
- 前端耗時少。 因為服務(wù)器端負(fù)責(zé)動態(tài)生成 HTML 內(nèi)容,瀏覽器只需要直接渲染頁面即可。尤其是移動端,更省電。
- 有利于 SEO 。 因為服務(wù)器端響應(yīng)的是完整的 HTML 頁面內(nèi)容,所以爬蟲更容易爬取獲得信息,更有利于 SEO 。
缺點:
- 占用服務(wù)器端資源。 即服務(wù)器端完成 HTML 頁面內(nèi)容的拼接,如果請求較多,會對服務(wù)器造成一定的訪問壓力。
- 不利于前后端分離,開發(fā)效率低。 使用服務(wù)器端渲染,則 無法進(jìn)行分工合作 ,尤其對于 前端復(fù)雜度高 的項目,不利于項目高效開發(fā)。
5.1.3 前后端分離 的 Web 開發(fā)模式
前后端分離的概念:前后端分離的開發(fā)模式,依賴于 Ajax 技術(shù)的廣泛應(yīng)用 。簡而言之,前后端分離的 Web 開發(fā)模式,就是 后端只負(fù)責(zé)提供 API 接口,前端使用 Ajax 調(diào)用接口 的開發(fā)模式。
5.1.4 前后端分離的優(yōu)缺點
優(yōu)點:
- 開發(fā)體驗好。 前端專注于 UI 頁面的開發(fā),后端專注于 api 的開發(fā),且前端有更多的選擇性。
- 用戶體驗好。 Ajax 技術(shù)的廣泛應(yīng)用,極大的提高了用戶的體驗,可以輕松實現(xiàn)頁面的局部刷新。
- 減輕了服務(wù)器端的渲染壓力。 因為頁面最終是在每個用戶的瀏覽器中生成的。
缺點:
不利于 SEO 。 因為完整的 HTML 頁面需要在客戶端動態(tài)拼接完成,所以爬蟲對無法爬取頁面的有效信息。(解決方案:利用 Vue 、 React 等前端框架的 SSR (server side render )技術(shù)能夠很好的解決 SEO 問題!)
5.1.5 如何選擇 Web 開發(fā)模式
不談業(yè)務(wù)場景而盲目選擇使用何種開發(fā)模式都是耍流氓。
- 比如企業(yè)級網(wǎng)站,主要功能是展示而沒有復(fù)雜的交互,并且需要良好的 SEO ,則這時我們就需要使用服務(wù)器端渲染;
- 而類似后臺管理項目,交互性比較強,不需要考慮 SEO ,那么就可以使用前后端分離的開發(fā)模式。
另外,具體使用何種開發(fā)模式并不是絕對的,為了同時兼顧 首頁的渲染速度 和 前后端分離的開發(fā)效率 ,一些網(wǎng)站采用了首屏服務(wù)器端渲染 + 其他頁面前后端分離的開發(fā)模式。
5.2 身份認(rèn)證
5.2.1 什么是 身份認(rèn)證
身份認(rèn)證(Authentication )又稱“身份驗證”、“鑒權(quán)”,是指 通過一定的手段,完成對用戶身份的確認(rèn) 。
- 日常生活中的身份認(rèn)證隨處可見,例如:高鐵的驗票乘車,手機(jī)的密碼或指紋解鎖,支付寶或微信的支付密碼等。
- 在 Web 開發(fā)中,也涉及到用戶身份的認(rèn)證,例如:各大網(wǎng)站的 手機(jī)驗證碼登錄 、 郵箱密碼登錄 、 二維碼登錄 等。
5.2.2 為什么需要身份認(rèn)證
身份認(rèn)證的目的,是為了 確認(rèn)當(dāng)前所聲稱為某種身份的用戶,確實是所聲稱的用戶 。例如,你去找快遞員取快遞,你要怎么證明這份快遞是你的。
在互聯(lián)網(wǎng)項目開發(fā)中,如何對用戶的身份進(jìn)行認(rèn)證,是一個值得深入探討的問題。例如,如何才能保證網(wǎng)站不會錯誤的將“馬云的存款數(shù)額”顯示到“馬化騰的賬戶”上。
5.2.3 不同開發(fā)模式下的 身份認(rèn)證
對于服務(wù)端渲染 和 前后端分離 這兩種開發(fā)模式來說,分別有著不同的身份認(rèn)證方案:
5.3 Session 認(rèn)證機(jī)制
5.3.1 HTTP協(xié)議的無狀態(tài)性
了解HTTP 協(xié)議的無狀態(tài)性是進(jìn)一步學(xué)習(xí) Session 認(rèn)證機(jī)制的必要前提。
HTTP協(xié)議的無狀態(tài)性,指的是客戶端的 每次 HTTP 請求都是獨立的 ,連續(xù)多個請求之間沒有直接的關(guān)系,服務(wù)器不會主動保留每次 HTTP 請求的狀態(tài) 。
5.3.2 如何突破 HTTP 無狀態(tài)的限制
對于超市來說,為了方便收銀員在進(jìn)行結(jié)算時給 VIP 用戶打折,超市可以為每個 VIP 用戶發(fā)放會員卡。
Note:現(xiàn)實生活中的會員卡身份認(rèn)證方式 ,在 Web 開發(fā)中的 專業(yè)術(shù)語 叫做 Cookie 。
5.3.3 什么是 Cookie
Cookie是 存儲在用戶瀏覽器中的一段不超過 4 KB 的字符串 。它由一個 名稱 (Name )、一個 值 (Value )和其它幾個用于控制 Cookie 有效期 、安全性、使用范圍 的 可選屬性 組成。
不同域名下的 Cookie 各自獨立,每當(dāng)客戶端發(fā)起請求時,會自動把當(dāng)前域名下 所有未過期的Cookie一同發(fā)送到服務(wù)器。
Cookie的幾大特性:
- 自動發(fā)送;
- 域名獨立;
- 過期時限;
- 4KB 限制。
5.3.4 Cookie 在身份認(rèn)證中的作用
客戶端第一次請求服務(wù)器的時候,服務(wù)器通過響應(yīng)頭的形式 ,向客戶端發(fā)送一個身份認(rèn)證的 Cookie ,客戶端會自動將 Cookie 保存在瀏覽器中。
隨后,當(dāng)客戶端瀏覽器每次請求服務(wù)器的時候,瀏覽器會自動將身份認(rèn)證相關(guān)的 Cookie 通過請求頭的形式發(fā)送給服務(wù)器,服務(wù)器即可驗明客戶端的身份。
5.3.5 Cookie不具有安全性
由于Cookie 是存儲在瀏覽器中的,而且瀏覽器也提供了讀寫 Cookie 的 API ,因此Cookie 很容易被偽造,不具有安全性。因此不建議服務(wù)器將重要的隱私數(shù)據(jù),通過 Cookie 的形式發(fā)送給瀏覽器。
注: 千萬不要使用 Cookie 存儲重要且隱私的數(shù)據(jù) !比如用戶的身份信息、密碼等。
5.3.6 提高 身份認(rèn)證的 安全性
為了防止客戶偽造會員卡,收銀員在拿到客戶出示的會員卡之后,可以在收銀機(jī)上進(jìn)行刷卡認(rèn)證 。只有收銀機(jī)確認(rèn)存在的會員卡,才能被正常使用。
這種 “ 會員卡 + 刷卡認(rèn)證 ” 的設(shè)計理念,就是 Session 認(rèn)證機(jī)制的精髓。
5.3.7 Session 的工作原理
5.4 在 Express 中使用 Session 認(rèn)證
5.4.1 安裝express-session中間件
在 Express 項目中,只需要安裝express-session中間件,即可在項目中使用 Session 認(rèn)證:
5.4.2 配置express-session中間件
express-session 中間件安裝成功后,需要通過 app.use () 來 注冊 session 中間件 ,示例代碼如下:
5.4.3 向 session 中存數(shù)據(jù)
當(dāng) express-session 中間件配置成功后,即可通過 req.session 來訪問和使用 session 對象,從而存儲用戶的關(guān)鍵信息:
5.4.4 從 session 中取數(shù)據(jù)
可以直接從req.session 對象上獲取之前存儲的數(shù)據(jù),示例代碼如下:
5.4.5 清空 session
調(diào)用 req.session.destroy() 函數(shù),即可清空服務(wù)器保存的 session 信息。
5.5 JWT認(rèn)證機(jī)制
5.5.1 了解 Session 認(rèn)證的局限性
Session 認(rèn)證機(jī)制 需要配合 Cookie 才能實現(xiàn) 。由于 Cookie 默認(rèn)不支持跨域訪問,所以,當(dāng)涉及到 前端跨域請求后端接口 的時候,需要做很多額外的配置,才能實現(xiàn)跨域 Session 認(rèn)證。
🔔 注意:
當(dāng)前端請求后端接口 不存在跨域問題 的時候, 推薦使用 Session 身份認(rèn)證機(jī)制。
當(dāng)前端需要 跨域請求后端接口的時候,不推薦使用 Session 身份認(rèn)證機(jī)制, 推薦使用 JWT 認(rèn)證機(jī)制。
5.5.2 什么是 JWT
JWT(英文全稱 JSON Web Token )是目前最流行的跨域認(rèn)證解決方案。
5.5.3 JWT的工作原理
總結(jié): 用戶的信息通過 Token 字符串的形式,保存在客戶端瀏覽器中。服務(wù)器通過還原 Token 字符串的形式來認(rèn)證用戶的身份。
5.5.4 4. JWT的組成部分
JWT 通常由三部分組成,分別是Header(頭部)、Payload(有效荷載)、Signature(簽名)。
三者之間使用英文的“.”分隔,格式如下:
下面是 JWT 字符串的示例:
5.5.5 JWT的三個部分各自代表的含義
JWT的三個組成部分,從前到后分別是 Header 、 Payload 、 Signature 。
其中:
- Payload 部分 才是真正的用戶信息 ,它是用戶信息經(jīng)過加密之后生成的字符串
- Header 和 Signature 是 安全性相關(guān) 的部分,只是為了保證 Token 的安全性。
5.5.6 JWT的使用方式
客戶端收到服務(wù)器返回的 JWT 之后,通常會將它儲存在 localStorage 或 sessionStorage 中。
此后,客戶端每次與服務(wù)器通信,都要帶上這個JWT 的字符串,從而進(jìn)行身份認(rèn)證。推薦的做法是 把 JWT 放在 HTTP請求頭的 Authorization 字段中 ,格式如下:
5.6 在 Express 中使用 JWT
5.6.1 安裝JWT相關(guān)的包
運行如下命令,安裝如下 2 個JWT 相關(guān)的包:
其中:
- jsonwebtoken 用于 生成 JWT 字符串;
- express-jwt 用于 將 JWT 字符串解析還原成 JSON 對象。
5.6.2 導(dǎo)入 JWT 相關(guān)的包
使用 require() 函數(shù),分別導(dǎo)入 JWT 相關(guān)的兩個包:
5.6.3 定義 secret 密鑰
為了 保證 JWT 字符串的安全性 ,防止 JWT 字符串在網(wǎng)絡(luò)傳輸過程中被別人破解,我們需要專門定義一個用于 加密 和 解密 的 secret 密鑰:
5.6.4 在登錄成功后生成 JWT 字符串
調(diào)用 jsonwebtoken 包提供的 sign() 方法,將用戶的信息加密成 JWT 字符串,響應(yīng)給客戶端:
5.6.5 將 JWT 字符串 還原為 JSON 對象
客戶端每次在訪問那些有權(quán)限接口的時候,都需要主動通過請求頭中的 Authorization 字段 ,將 Token 字符串發(fā)送到服務(wù)器進(jìn)行身份認(rèn)證。
此時,服務(wù)器可以通過express-wt 這個中間件,自動將客戶端發(fā)送過來的 Token 解析還原成 JSON 對象:
5.6.6 使用 req.user 獲取用戶信息
當(dāng) express-jwt 這個中間件配置成功之后,即可在那些有權(quán)限的接口中,使用 req.user 對象,來訪問從 JWT 字符串中解析出來的用戶信息了,示例代碼如下:
5.6.7 捕獲解析 JWT 失敗后產(chǎn)生的錯誤
當(dāng)使用 express-jwt 解析 Token 字符串時,如果客戶端發(fā)送過來的 Token 字符串 過期 或 不合法 ,會產(chǎn)生一個 解析失敗的錯誤,影響項目的正常運行。我們可以通過 Express 的錯誤中間件 ,捕獲這個錯誤并進(jìn)行相關(guān)的處理,示例代碼如下:
總結(jié)
以上是生活随笔為你收集整理的Node.js 入门详解(四)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Vue+mui实现图片的本地缓存
- 下一篇: Excel 表单控件之 CheckBox