亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

前端node Session和JWT鑒權(quán)登錄示例詳解

 更新時間:2022年07月06日 12:02:23   作者:heyyyfx  
關(guān)于前端鑒權(quán)登錄是比較常見的需求了,本文將從服務(wù)端渲染和前后端分離的不同角度下演示鑒權(quán),為大家介紹前端node Session和JWT鑒權(quán)登錄示例詳解

服務(wù)端渲染及session鑒權(quán)

服務(wù)端渲染

服務(wù)端渲染簡單來說就是前端頁面是由服務(wù)器通過字符串拼接動態(tài)生成的,客戶端不需要額外通過Ajax請求參數(shù),只需要做好渲染工作即可。

優(yōu)點

  • 前端耗時少,前端只需要請求一次接口就能將數(shù)據(jù)渲染出來,首屏加載速度變快。
  • 利于SEO,因為服務(wù)器端相應(yīng)的是完整的html頁面內(nèi)容,利于爬蟲獲取信息。

缺點

  • 占用服務(wù)器資源,請求過多會造成訪問壓力。
  • 不利于前后端分類,并且前端復(fù)雜度高時不利于開發(fā)。

服務(wù)端身份驗證Session原理

對于服務(wù)端渲染,推薦使用Session認(rèn)證機制,再次之前,先說明一下cookie

比如你可以在baidu.com看到以下cookie:

session的鑒權(quán)就是利用了cookie,用戶調(diào)用登錄接口,完成賬號密碼的校驗之后,將用戶信息或者其他校驗信息生成為cookie字符串,返回給用戶,同時將cookie存儲在服務(wù)器內(nèi)存,用戶請求其他接口時,會在請求頭自動將cookie發(fā)送給服務(wù)器,服務(wù)器會通過與服務(wù)器內(nèi)存中的用戶信息匹配,如果匹配成功,則返回客戶端想要的內(nèi)容,否則拋出錯誤提示客戶端需要重新登錄。大致流程圖如下:

實踐操作

接下來我們來進行實踐操作,在此之前請預(yù)先執(zhí)行 npm i express express-session,安裝所需要的模塊。

index.js文件的代碼如下:

// 導(dǎo)入 express 模塊
const express = require('express')
// 創(chuàng)建 express 的服務(wù)器實例
const app = express()
// 01:配置 Session 中間件
const session = require('express-session')
app.use(
  session({
    secret: 'heyyyyfx',//此處的secret密鑰可以是任意字符串,是你自己制定的專屬加密方案,此處筆者將以自己的名字為例
    resave: false,//無需在意,但是要寫上
    saveUninitialized: true,//無需在意,但是要寫上
  })
)
// 托管靜態(tài)頁面,此處筆者代理了一個靜態(tài)文件,文件內(nèi)容下文可見。
app.use(express.static('./pages'))
// 解析 POST 提交過來的表單數(shù)據(jù)
app.use(express.urlencoded({ extended: false }))
// 登錄的 API 接口
app.post('/api/login', (req, res) => {
  // 判斷用戶提交的登錄信息是否正確,此處寫死一個賬號密碼校驗,在實際開發(fā)中肯定是需要數(shù)據(jù)庫匹配。
  if (req.body.username !== 'admin' || req.body.password !== '000000') {
    return res.send({ status: 1, msg: '登錄失敗' })
  }
  // 02:請將登錄成功后的用戶信息,保存到 Session 中
  // 注意:只有成功配置了 express-session 這個中間件之后,才能夠通過 req 點出來 session 這個屬性
  req.session.user = req.body // 用戶的信息,我們將用戶的信息轉(zhuǎn)換成cookie字符串返回給用戶。
  req.session.islogin = true // 用戶的登錄狀態(tài),也是我們鑒權(quán)的參考
  res.send({ status: 0, msg: '登錄成功' })
})
// 獲取用戶姓名的接口
app.get('/api/username', (req, res) => {
  // 03:請從 Session 中獲取用戶的名稱,響應(yīng)給客戶端
  if (!req.session.islogin) {//此處就進行了鑒權(quán),看用戶的cookie是否有我們之前發(fā)送給他的islogin字段。
    return res.send({ status: 1, msg: 'fail' })
  }
  res.send({
    status: 0,
    msg: 'success',
    username: req.session.user.username,
  })
})
// 退出登錄的接口
app.post('/api/logout', (req, res) => {
  // 04:清空 Session 信息
  req.session.destroy()
  res.send({
    status: 0,
    msg: '退出登錄成功',
  })
})
// 調(diào)用 app.listen 方法,指定端口號并啟動web服務(wù)器
app.listen(80, function () {
  console.log('Express server running at http://127.0.0.1:80')
})

筆者在此只附上index.js的內(nèi)容,其他文件內(nèi)容可以在文末中拿到源碼。

其他

缺陷

可以看到,Session機制需要cookie的配合才能實現(xiàn),因此cookie的的缺點或特性也就會影響到Session鑒權(quán),比如,cookie是默認(rèn)不支持跨域的,當(dāng)前端跨域請求后端接口時,需要做很多額外的配置,這也就是為什么Session推薦在服務(wù)端使用。

關(guān)于跨域

筆者在本文中說到的的跨域問題,指的是客戶端和服務(wù)端二者的跨域,如果讀者下載了源碼,可以看到筆者是在app.js(index.js)中使用app.use(express.static('./pages'))進行了靜態(tài)托管,以此來保證客戶端和服務(wù)端都是locallhost:80,是同源的。感興趣的讀者可以嘗試用live Sever來代理Index.html文件,看看效果如何,在此之前記得引入cors中間件支持跨域。

想說的

其實筆者在此只是簡單講解了Session鑒權(quán)的大致原理以及進行了簡單的實現(xiàn),在實際真實開發(fā)中,首先我們不建議將用戶信息返回生成cookie字符串再返回給客戶端,因為這是非常隱私的信息,其次要知道cookie是可以直接在客戶端更改的,因此鑒權(quán)關(guān)鍵字段也是需要斟酌的,現(xiàn)實開發(fā)是非常嚴(yán)謹(jǐn)?shù)模堊x者在實際使用時秉承嚴(yán)謹(jǐn)?shù)膽B(tài)度。

JWT鑒權(quán)

適用情況

上文已經(jīng)說到了,session會受到跨域的影響,因此在前后端分離開發(fā)以及存在跨域的情況下,我們推薦使用JWT鑒權(quán)。

JWT鑒權(quán)原理

JWT原理和Session大致相同,不同的點在于,JWT生成的Token字符串需要客戶端手動存儲在localStoragesessionStorage中。再次請求時,客戶端需要將Token放在請求頭的Authorization字段中。

JWT

jwt是Json Web Token的縮寫,它的結(jié)構(gòu)分為三個部分:header.payload.signature,兩兩之間用【.】分隔。

header

header是一個JSON結(jié)構(gòu),主要包含token的類型(即JWT),簽名的算法

{
    "alg":"HS256",
    "typ":"JWT"
}

payload

payload也是JSON結(jié)構(gòu),它是存放有效信息的地方,JWT官方提供了一些官方字段,你也可以定義自己的私有字段,其中官方字段如下:

  • iss:簽發(fā)人
  • exp:token過期時間
  • sub:主題
  • aud:受眾
  • nbf:生效時間
  • iat:簽發(fā)時間
  • jti:編號

但是注意,payload是默認(rèn)不加密的,因此建議自己定義的私有字段不要放入用戶私密信息。

signature

它是用戶自己定義的字段,用戶要設(shè)計一個獨一無二且保證不會外泄的密鑰,通過下方算法生成簽名,用于未來的身份驗證。

 HMACSHA256(
 base64UrlEncode(header) + "." +
 base64UrlEncode(payload),
 secret)

實踐

首先安裝必要的npm包,執(zhí)行以下指令:

npm i body-parser cors express express-jwt jsonwebtoken,

在index.js中寫入以下內(nèi)容:

// 導(dǎo)入 express 模塊
const express = require('express')
// 創(chuàng)建 express 的服務(wù)器實例
const app = express()
// 01:安裝并導(dǎo)入 JWT 相關(guān)的兩個包,分別是 jsonwebtoken 和 express-jwt
const jwt = require('jsonwebtoken')
const expressJWT = require('express-jwt')
// 允許跨域資源共享
const cors = require('cors')
app.use(cors())
// 解析 post 表單數(shù)據(jù)的中間件
const bodyParser = require('body-parser')
app.use(bodyParser.urlencoded({ extended: false }))
// 02:定義 secret 密鑰,建議將密鑰命名為 secretKey
const secretKey = 'heyyyyfx'
// 04:注冊將 JWT 字符串解析還原成 JSON 對象的中間件
// 注意:只要配置成功了 express-jwt 這個中間件,就可以把解析出來的用戶信息,掛載到 req.user 屬性上
// unless指定哪些接口不需要訪問權(quán)限,即白名單。
app.use(expressJWT({ secret: secretKey }).unless({ path: [/^\/api\//] }))
// 登錄接口
app.post('/api/login', function (req, res) {
  // 將 req.body 請求體中的數(shù)據(jù),轉(zhuǎn)存為 userinfo 常量
  const userinfo = req.body
  // 登錄失敗
  if (userinfo.username !== 'admin' || userinfo.password !== '000000') {
    return res.send({
      status: 400,
      message: '登錄失??!',
    })
  }
  // 登錄成功
  // 03:在登錄成功之后,調(diào)用 jwt.sign() 方法生成 JWT 字符串。并通過 token 屬性發(fā)送給客戶端
  // 參數(shù)1:用戶的信息對象
  // 參數(shù)2:加密的秘鑰
  // 參數(shù)3:配置對象,可以配置當(dāng)前 token 的有效期,本處設(shè)置的是30S
  // 記住:千萬不要把密碼加密到 token 字符中
  const tokenStr = jwt.sign({ username: userinfo.username }, secretKey, { expiresIn: '30s' })
  res.send({
    status: 200,
    message: '登錄成功!',
    token: tokenStr, // 要發(fā)送給客戶端的 token 字符串
  })
})
// 這是一個有權(quán)限的 API 接口
app.get('/admin/getinfo', function (req, res) {
  // 05:使用 req.user 獲取用戶信息,并使用 data 屬性將用戶信息發(fā)送給客戶端
  console.log(req.user)
  res.send({
    status: 200,
    message: '獲取用戶信息成功!',
    data: req.user, // 要發(fā)送給客戶端的用戶信息
  })
})
// 06:使用全局錯誤處理中間件,捕獲解析 JWT 失敗后產(chǎn)生的錯誤
app.use((err, req, res, next) => {
  // 這次錯誤是由 token 解析失敗導(dǎo)致的
  if (err.name === 'UnauthorizedError') {
    return res.send({
      status: 401,
      message: '無效的token',
    })
  }
  res.send({
    status: 500,
    message: '未知的錯誤',
  })
})
// 調(diào)用 app.listen 方法,指定端口號并啟動web服務(wù)器
app.listen(8888, function () {
  console.log('Express server running at http://127.0.0.1:8888')
})

開啟node服務(wù)后,用postman進行測試,調(diào)用登錄接口后,拿到返回的Token:

隨后調(diào)用獲取用戶信息接口,注意,該接口是需要權(quán)限的,我們需要在請求頭中加入Authorization字段,值為Token,同時有個注意事項,Token值前需要加入Bearer關(guān)鍵字,用空格分隔,這是必要的操作。

如果你操作的過慢,就會看到如下報錯,這是因為我們的有效期只有30s。

不妨再調(diào)用一次登錄接口,同時迅速用新的Token請求用戶信息接口,結(jié)果如下,說明成功。

想說的

Token有效期問題

在本文中,我們是自己為Token設(shè)置了30s的有效期,但如果你用心觀察國內(nèi)外的網(wǎng)站,貌似沒有出現(xiàn)用著用著就突然返回到登錄界面讓你突然重新登陸的,難道是因為他們的有效期設(shè)置的特別長?

其實在真實開發(fā)中,Token的有效期往往不會用這種方式設(shè)置,大多數(shù)有效期是動態(tài)的,打個比方,只有當(dāng)你在當(dāng)前頁面半小時之內(nèi)沒有任何請求之后,才會讓你的Token自動失效,這種是怎樣實現(xiàn)的?其實有很多種實現(xiàn)方案,筆者在此只舉一種例子,讀者可以先了解一下redis數(shù)據(jù)庫。

redis數(shù)據(jù)庫及動態(tài)Token解決方案

redis的優(yōu)點在此不做過多說明,感興趣的可以自行查閱,redis數(shù)據(jù)庫提供了一個叫expire的命令,命令用于設(shè)置 key 的過期時間,key 過期后將不再可用。單位以秒計。

我們可以以此為基礎(chǔ),當(dāng)用戶請求登錄接口時,我們將Token返回給用戶,同時我們將這個Token作為Key存儲到數(shù)據(jù)庫,Value為這個用戶的個人信息或其他內(nèi)容,并為這個key設(shè)置一個定時刪除命令,當(dāng)用戶在有效期時,數(shù)據(jù)庫將用戶請求接口時攜帶的Token進行查詢,看是否存在這個Token的key,當(dāng)可以被查詢時,說明有效期還在(因為過了有效期這個Token就會被刪除,表中就無法查詢到這個Token),同時再次對這個Key執(zhí)行定時刪除任務(wù),達到覆蓋上一次刪除定時任務(wù),延長有效期的作用,只有當(dāng)沒有接口請求后,刪除任務(wù)執(zhí)行,Token才會失效,以此來實現(xiàn)動態(tài)Token的目的,至于覆蓋定時刪除任務(wù)這個操作,因為是每一個操作相關(guān)的接口都要進行,因此不妨將它封裝成全局中間件,避免在每個接口中都寫下重復(fù)代碼。

最后

源碼:https://github.com/fengxiao1998/SessionAndJWT

本文所有內(nèi)容都是基于node的鑒權(quán),相比于純后端Java開發(fā)肯定會有很多不足之處,對于前端而言只是和大家一起了解學(xué)習(xí)鑒權(quán)相關(guān)知識,更多關(guān)于node Session JWT鑒權(quán)登錄的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Node.js log4js日志管理詳解

    Node.js log4js日志管理詳解

    日志對任何的應(yīng)用來說都是至關(guān)重要的,下面這篇文章主要給大家介紹了關(guān)于Node.js log4js日志管理的相關(guān)資料,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考借鑒,下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-07-07
  • nodejs中的fiber(纖程)庫詳解

    nodejs中的fiber(纖程)庫詳解

    這篇文章主要介紹了nodejs中的fiber(纖程)庫詳解,本文講解了node-fibers的安裝、API介紹、方法使用示例等內(nèi)容,需要的朋友可以參考下
    2015-03-03
  • 使用nodejs實現(xiàn)JSON文件自動轉(zhuǎn)Excel的工具(推薦)

    使用nodejs實現(xiàn)JSON文件自動轉(zhuǎn)Excel的工具(推薦)

    這篇文章主要介紹了使用nodejs實現(xiàn),JSON文件自動轉(zhuǎn)Excel的工具,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-06-06
  • 詳解Node.js使用token進行認(rèn)證的簡單示例

    詳解Node.js使用token進行認(rèn)證的簡單示例

    這篇文章主要介紹了詳解Node.js使用token進行認(rèn)證的簡單示例,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-05-05
  • Node的事件處理和readline模塊詳解

    Node的事件處理和readline模塊詳解

    這篇文章主要為大家詳細介紹了Node的事件處理和readline模塊,使用數(shù)據(jù)庫,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • Node server生成Swagger接口文檔步驟詳解

    Node server生成Swagger接口文檔步驟詳解

    本文介紹使用NodeJs搭建的后端server快速生成Swagger接口文檔的技巧,本文有詳細的步驟講解,通過代碼示例給大家介紹的非常詳細,具有一定的參考價值,需要的朋友可以參考下
    2024-01-01
  • 基于node的cli工具開發(fā)使用詳解

    基于node的cli工具開發(fā)使用詳解

    這篇文章主要為大家介紹了基于node的cli工具開發(fā)使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-03-03
  • 使用nodejs開發(fā)cli項目實例

    使用nodejs開發(fā)cli項目實例

    這篇文章主要介紹了使用nodejs開發(fā)cli項目實例,本文講解使用generator-cli-starter實現(xiàn)cli項目的開發(fā),需要的朋友可以參考下
    2015-06-06
  • 基于NodeJS的前后端分離的思考與實踐(四)安全問題解決方案

    基于NodeJS的前后端分離的思考與實踐(四)安全問題解決方案

    本文就在前后端分離模式的架構(gòu)下,針對前端在Web開發(fā)中,所遇到的安全問題以及應(yīng)對措施和注意事項,并提出解決方案。
    2014-09-09
  • Windows系統(tǒng)下安裝Node.js的步驟圖文詳解

    Windows系統(tǒng)下安裝Node.js的步驟圖文詳解

    這篇文章主要給大家介紹了Windows系統(tǒng)下Node.js的安裝教程,Node.js是用于后端編程的JavaScript框架,文中給出了詳細圖文介紹,有需要的朋友可以參考下,下面來一起看看吧。
    2016-11-11

最新評論