最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Node.js實(shí)現(xiàn)JWT認(rèn)證的流程步驟

 更新時(shí)間:2025年06月24日 09:19:28   作者:盛夏綻放  
JSON?Web?Tokens?(JWT)?是現(xiàn)代?Web?開發(fā)中廣泛使用的身份驗(yàn)證機(jī)制,本文將用生動(dòng)的方式帶你全面了解?JWT?在?Node.js?中的實(shí)現(xiàn),包括生成、驗(yàn)證和各種相關(guān)方法,需要的朋友可以參考下

一、JWT 是什么?為什么需要它?

想象一下你去參加一個(gè)音樂會(huì),入場時(shí)需要出示門票。這張門票包含你的座位信息,并有防偽標(biāo)識(shí)。JWT 就像這張數(shù)字門票:

  • 包含信息:存儲(chǔ)用戶身份數(shù)據(jù)(如用戶ID)
  • 防偽標(biāo)識(shí):通過簽名防止篡改
  • 有效期:像門票一樣有使用期限

傳統(tǒng) session 與 JWT 對(duì)比

特性SessionJWT
存儲(chǔ)位置服務(wù)器內(nèi)存/數(shù)據(jù)庫客戶端
擴(kuò)展性跨服務(wù)器共享困難天然支持分布式
跨域支持需要額外配置原生支持
移動(dòng)端友好度一般非常好
安全性依賴 Cookie 安全依賴 Token 存儲(chǔ)方式

二、JWT 的結(jié)構(gòu)解析

一個(gè) JWT 看起來像這樣:
xxxxx.yyyyy.zzzzz

它由三部分組成,用點(diǎn)(.)分隔:

Header (頭部) - xxxxx

{
  "alg": "HS256",  // 簽名算法
  "typ": "JWT"     // 令牌類型
}

Payload (負(fù)載) - yyyyy

{
  "sub": "1234567890",  // 主題(用戶ID)
  "name": "John Doe",    // 自定義數(shù)據(jù)
  "iat": 1516239022     // 簽發(fā)時(shí)間
}

Signature (簽名) - zzzzz

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

可視化流程

[Header JSON] → Base64編碼 → xxxxx
[Payload JSON] → Base64編碼 → yyyyy
[xxxxx.yyyyy + 密鑰] → 簽名算法 → zzzzz
最終令牌:xxxxx.yyyyy.zzzzz

三、Node.js 中實(shí)現(xiàn) JWT

1. 安裝 jsonwebtoken 包

const jwt = require('jsonwebtoken');
const secret = 'your-secret-key'; // 應(yīng)該存儲(chǔ)在環(huán)境變量中

// 用戶登錄成功后生成token
function generateToken(user) {
  return jwt.sign(
    {
      userId: user.id,
      username: user.username,
      role: user.role
    },
    secret,
    {
      expiresIn: '1h', // 1小時(shí)后過期
      issuer: 'your-company', // 簽發(fā)者
      audience: 'your-app-name' // 接收方
    }
  );
}

參數(shù)詳解表

參數(shù)類型必填說明
payloadObject/String要編碼的數(shù)據(jù)
secretString簽名密鑰
optionsObject配置選項(xiàng)

常用 options

選項(xiàng)示例值說明
expiresIn‘1h’/‘15m’/‘7d’有效期
algorithm‘HS256’簽名算法
issuer‘your-app’簽發(fā)者
audience‘client-app’接收方
subject‘user-auth’主題

3. 驗(yàn)證 JWT

function verifyToken(token) {
  try {
    return jwt.verify(token, secret, {
      issuer: 'your-company',
      audience: 'your-app-name'
    });
  } catch (err) {
    console.error('Token驗(yàn)證失敗:', err.message);
    return null;
  }
}

// 使用示例
const token = generateToken({id: 1, username: 'john', role: 'admin'});
const decoded = verifyToken(token);

驗(yàn)證流程示意圖

客戶端請(qǐng)求 → [攜帶Token] → 服務(wù)器
       ↓
[提取Authorization頭]
       ↓
[拆分Bearer和Token]
       ↓
[jwt.verify()驗(yàn)證]
       ↓
[有效] → 繼續(xù)處理請(qǐng)求
       ↓
[無效] → 返回401錯(cuò)誤

4. 錯(cuò)誤處理大全

JWT 驗(yàn)證可能拋出以下錯(cuò)誤:

錯(cuò)誤類型觸發(fā)條件處理建議
JsonWebTokenError無效token返回401
TokenExpiredErrortoken過期返回401,提示刷新
NotBeforeError未到生效時(shí)間等待或返回403
SyntaxErrortoken格式錯(cuò)誤返回400

錯(cuò)誤處理增強(qiáng)版

function handleTokenError(err) {
  switch(err.name) {
    case 'JsonWebTokenError':
      return { status: 401, message: '無效令牌' };
    case 'TokenExpiredError':
      return { status: 401, message: '令牌已過期,請(qǐng)重新登錄' };
    case 'NotBeforeError':
      return { status: 403, message: '令牌尚未生效' };
    default:
      return { status: 400, message: '令牌處理錯(cuò)誤' };
  }
}

四、高級(jí)應(yīng)用場景

1. 刷新令牌機(jī)制

[登錄成功]
  ↓
[發(fā)放 access_token (短有效期) + refresh_token (長有效期)]
  ↓
[access_token過期] → [用refresh_token獲取新access_token]
  ↓
[refresh_token過期] → [要求重新登錄]

實(shí)現(xiàn)代碼:

// 生成令牌對(duì)
function generateTokenPair(user) {
  const accessToken = jwt.sign(
    { userId: user.id }, 
    secret, 
    { expiresIn: '15m' }
  );
  
  const refreshToken = jwt.sign(
    { userId: user.id, tokenType: 'refresh' },
    secret,
    { expiresIn: '7d' }
  );
  
  return { accessToken, refreshToken };
}

// 刷新access token
function refreshAccessToken(refreshToken) {
  const decoded = jwt.verify(refreshToken, secret);
  if (decoded.tokenType !== 'refresh') {
    throw new Error('非法的refresh token');
  }
  return jwt.sign({ userId: decoded.userId }, secret, { expiresIn: '15m' });
}

2. 在不同路由中的驗(yàn)證中間件

// 基礎(chǔ)驗(yàn)證中間件
function authenticateJWT(req, res, next) {
  const authHeader = req.headers.authorization;
  
  if (authHeader) {
    const token = authHeader.split(' ')[1];
    
    jwt.verify(token, secret, (err, user) => {
      if (err) {
        const error = handleTokenError(err);
        return res.status(error.status).json(error);
      }
      
      req.user = user;
      next();
    });
  } else {
    res.sendStatus(401);
  }
}

// 角色檢查中間件
function requireRole(role) {
  return (req, res, next) => {
    if (req.user?.role !== role) {
      return res.status(403).json({ message: '權(quán)限不足' });
    }
    next();
  };
}

// 使用示例
router.get('/admin', authenticateJWT, requireRole('admin'), (req, res) => {
  res.json({ message: '歡迎管理員' });
});

五、安全最佳實(shí)踐

密鑰管理

  • 永遠(yuǎn)不要將密鑰硬編碼在代碼中
  • 使用環(huán)境變量或密鑰管理服務(wù)
  • 定期輪換密鑰

Token 存儲(chǔ)

  • 前端:使用 HttpOnly + Secure 的 Cookie 比 localStorage 更安全
  • 避免在 URL 中傳遞 token

額外安全措施

// 示例:增加IP綁定
function generateToken(user, ip) {
  return jwt.sign({
    userId: user.id,
    ip: ip // 綁定用戶當(dāng)前IP
  }, secret, { expiresIn: '1h' });
}

function verifyToken(token, ip) {
  const decoded = jwt.verify(token, secret);
  if (decoded.ip !== ip) {
    throw new Error('IP地址不匹配');
  }
  return decoded;
}

六、常見問題解答

Q: JWT 和 Session Cookie 哪個(gè)更好?

A: 沒有絕對(duì)的好壞,取決于場景:

  • 需要分布式/無狀態(tài) → JWT
  • 需要即時(shí)撤銷 → Session
  • 移動(dòng)端應(yīng)用 → JWT
  • 傳統(tǒng)Web應(yīng)用 → 兩者皆可

Q: JWT 過期后如何處理?

A: 兩種方案:

  • 讓用戶重新登錄
  • 使用refresh token機(jī)制自動(dòng)獲取新token

Q: 如何實(shí)現(xiàn)強(qiáng)制下線?

A: JWT 本身難以實(shí)現(xiàn),可以考慮:

  • 使用短有效期 + refresh token
  • 維護(hù)一個(gè)黑名單(部分犧牲無狀態(tài)特性)
  • 在token中存儲(chǔ)版本號(hào),修改版本號(hào)使舊token失效

七、完整示例代碼

const express = require('express');
const jwt = require('jsonwebtoken');
const app = express();
require('dotenv').config();

const SECRET = process.env.JWT_SECRET || 'fallback-secret';
const PORT = process.env.PORT || 3000;

// 模擬用戶數(shù)據(jù)庫
const users = [
  { id: 1, username: 'admin', password: 'admin123', role: 'admin' },
  { id: 2, username: 'user', password: 'user123', role: 'user' }
];

app.use(express.json());

// 登錄路由
app.post('/login', (req, res) => {
  const { username, password } = req.body;
  const user = users.find(u => u.username === username && u.password === password);
  
  if (!user) {
    return res.status(401).json({ message: '用戶名或密碼錯(cuò)誤' });
  }
  
  const token = jwt.sign(
    { userId: user.id, role: user.role },
    SECRET,
    { expiresIn: '15m' }
  );
  
  res.json({ token });
});

// 受保護(hù)路由
app.get('/profile', authenticateJWT, (req, res) => {
  const user = users.find(u => u.id === req.user.userId);
  res.json({ 
    id: user.id,
    username: user.username,
    role: user.role
  });
});

// 管理員路由
app.get('/admin-stats', authenticateJWT, (req, res, next) => {
  if (req.user.role !== 'admin') {
    return res.status(403).json({ message: '需要管理員權(quán)限' });
  }
  res.json({ stats: '敏感管理數(shù)據(jù)' });
});

// JWT驗(yàn)證中間件
function authenticateJWT(req, res, next) {
  const authHeader = req.headers.authorization;
  
  if (authHeader && authHeader.startsWith('Bearer ')) {
    const token = authHeader.split(' ')[1];
    
    jwt.verify(token, SECRET, (err, user) => {
      if (err) {
        const error = handleTokenError(err);
        return res.status(error.status).json(error);
      }
      
      req.user = user;
      next();
    });
  } else {
    res.status(401).json({ message: '需要認(rèn)證令牌' });
  }
}

// 錯(cuò)誤處理函數(shù)
function handleTokenError(err) {
  switch(err.name) {
    case 'JsonWebTokenError':
      return { status: 401, message: '無效令牌' };
    case 'TokenExpiredError':
      return { status: 401, message: '令牌已過期,請(qǐng)重新登錄' };
    default:
      return { status: 400, message: '令牌處理錯(cuò)誤' };
  }
}

app.listen(PORT, () => {
  console.log(`服務(wù)器運(yùn)行在 http://localhost:${PORT}`);
});

結(jié)語

JWT 就像數(shù)字世界的護(hù)照,它輕巧、自包含且安全。通過本文的學(xué)習(xí),你應(yīng)該已經(jīng)掌握了:

  • JWT 的結(jié)構(gòu)和工作原理
  • 如何在 Node.js 中生成和驗(yàn)證 JWT
  • 各種相關(guān)方法和配置選項(xiàng)
  • 高級(jí)應(yīng)用場景和安全實(shí)踐

記住,沒有絕對(duì)安全的系統(tǒng),JWT 只是工具,合理的使用方式和適當(dāng)?shù)陌踩胧┎攀顷P(guān)鍵?,F(xiàn)在就去你的 Node.js 項(xiàng)目中實(shí)踐這些知識(shí)吧!

以上就是Node.js實(shí)現(xiàn)JWT認(rèn)證的流程步驟的詳細(xì)內(nèi)容,更多關(guān)于Node.js JWT認(rèn)證的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 一文秒懂nodejs中的異步編程

    一文秒懂nodejs中的異步編程

    這篇文章主要介紹了深入理解nodejs中的異步編程,本文給大家介紹的非常想詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-01-01
  • node異步使用await和不用await的區(qū)別實(shí)例分析

    node異步使用await和不用await的區(qū)別實(shí)例分析

    這篇文章主要介紹了node異步使用await和不用await的區(qū)別,結(jié)合實(shí)例形式分析了node.js異步使用await和不用await的實(shí)例中,同步與異步執(zhí)行的區(qū)別,需要的朋友可以參考下
    2023-06-06
  • 淺談Node.js 子進(jìn)程與應(yīng)用場景

    淺談Node.js 子進(jìn)程與應(yīng)用場景

    這篇文章主要介紹了淺談Node.js 子進(jìn)程與應(yīng)用場景,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-01-01
  • express框架+bootstrap美化ejs模板實(shí)例分析

    express框架+bootstrap美化ejs模板實(shí)例分析

    這篇文章主要介紹了express框架+bootstrap美化ejs模板,結(jié)合實(shí)例形式分析了express框架引入bootstrap結(jié)合ejs模版引擎相關(guān)操作技巧與注意事項(xiàng),需要的朋友可以參考下
    2023-05-05
  • 如何寫Node.JS版本小游戲

    如何寫Node.JS版本小游戲

    JavaScript的出現(xiàn)催動(dòng)了前端開發(fā)的萌芽,前后端分離促進(jìn)了Vue、React等開發(fā)框架的發(fā)展,Weex、React-Native等的演變賦予了并存多端開發(fā)的能力,而Node.JS的面世無疑是推動(dòng)了Web全棧開發(fā)的步伐。
    2021-05-05
  • 詳解使用Node.js 將txt文件轉(zhuǎn)為Excel文件

    詳解使用Node.js 將txt文件轉(zhuǎn)為Excel文件

    這篇文章主要介紹了詳解使用Node.js 將txt文件轉(zhuǎn)為Excel文件,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-07-07
  • 初始Nodejs

    初始Nodejs

    本文屬于nodejs的基礎(chǔ)知識(shí)介紹篇,從nodejs的基本概念,到架構(gòu)示意圖,同步異步等方面做了詳細(xì)的解答,是篇非常不錯(cuò)的文章
    2014-11-11
  • Node.js?連接?MySql?統(tǒng)計(jì)組件屬性的使用情況解析

    Node.js?連接?MySql?統(tǒng)計(jì)組件屬性的使用情況解析

    這篇文章主要為大家介紹了Node.js?連接?MySql?統(tǒng)計(jì)組件屬性的使用情況解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-10-10
  • node.js使用express-jwt報(bào)錯(cuò):expressJWT?is?not?a?function解決

    node.js使用express-jwt報(bào)錯(cuò):expressJWT?is?not?a?function解決

    這篇文章主要給大家介紹了關(guān)于node.js使用express-jwt報(bào)錯(cuò):expressJWT?is?not?a?function解決的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2023-03-03
  • Nodejs異步回調(diào)之異常處理實(shí)例分析

    Nodejs異步回調(diào)之異常處理實(shí)例分析

    這篇文章主要介紹了Nodejs異步回調(diào)之異常處理,結(jié)合實(shí)例形式分析了nodejs基于中間件進(jìn)行異步回調(diào)異常處理過程出現(xiàn)的問題與相應(yīng)的解決方法,需要的朋友可以參考下
    2018-06-06

最新評(píng)論

固阳县| 忻城县| 措美县| 天津市| 五常市| 卓尼县| 绥宁县| 闽侯县| 伊宁县| 平舆县| 定日县| 闵行区| 马尔康县| 建昌县| 武隆县| 无锡市| 布拖县| 凤冈县| 乌兰浩特市| 溧阳市| 工布江达县| 永福县| 册亨县| 井陉县| 准格尔旗| 梁山县| 寻乌县| 浠水县| 定西市| 屏山县| 鄱阳县| 盘山县| 台北县| 四川省| 永福县| 平潭县| 罗田县| 安顺市| 巴林右旗| 大冶市| 镇巴县|