🪪 前端的通行证!手把手带你玩转 JWT 身份验证(从登录到保命)

152 阅读5分钟

✍ 前言:登录不是登录,是一场身份的较量

还记得你第一次做登录功能吗?是不是写个 /login,用户名密码验证完,直接 res.send("登录成功!") 就结束了?

但问题来了:

  • 登录之后,怎么知道后续请求是你发的?
  • 每次请求都要查数据库?太累了吧?
  • Session 你听过,JWT 呢?好像高级点?

今天,就来带你走一波 JWT 登录认证的实战路线,让你从“登录小白”进阶为“身份掌控者”!


🧠 什么是 JWT?

JWT,全称 JSON Web Token,是一种跨服务的身份令牌机制。

它的核心目标只有一个:

✅ 用户登录之后,给他一个“身份令牌”,以后每次请求拿这个令牌就行,无须每次都查数据库,也不需要维护复杂的 Session。


🧱 JWT 的结构是啥?

JWT 长得像一段超长字符串,比如下面这样:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJ1c2VySWQiOjEyMywidXNlcm5hbWUiOiJhamF4IiwiaWF0IjoxNjg1MDA2NDAwfQ.
W5I5dFTFG9SGzSNRkZz_PdD3fgz0Z3xLpoHDZq9aXGM

被点(.)分成三段,分别代表:

部分含义示例内容
Header算法和类型{"alg":"HS256","typ":"JWT"}
Payload数据内容(比如 userId){"userId":123,"username":"ajax"}
Signature签名(加密串)防篡改的验证串

⚠ 注意:Payload 是 明文 Base64 编码,不要写敏感信息!


🚀 使用流程(通俗易懂版)

🧑‍💻 后端的套路:

  1. 用户发起登录(POST /login)

  2. 后端验证账号密码正确

  3. 使用 secret 生成 JWT:

    const token = jwt.sign({ userId: 123 }, 'secret', { expiresIn: '2h' })
    
  4. token 发给前端

🖥️ 前端的操作:

  1. 登录成功后拿到 token

  2. 保存到 localStorage(或 cookie)

  3. 后续请求中加上:

    fetch('/api/user', {
      headers: {
        'Authorization': 'Bearer ' + token
      }
    })
    

🔍 后端怎么验证?

const token = req.headers.authorization?.split(' ')[1]
const decoded = jwt.verify(token, 'secret')
console.log(decoded) // => { userId: 123, iat: xxx, exp: xxx }

🧪 实战演练:Node + Express + JWT 登录系统

🎯 安装依赖

npm install express jsonwebtoken body-parser

🧩 示例代码

const express = require('express')
const jwt = require('jsonwebtoken')
const bodyParser = require('body-parser')

const app = express()
const SECRET = 'my-secret'

app.use(bodyParser.json())

// 模拟用户登录
app.post('/login', (req, res) => {
  const { username, password } = req.body
  if (username === 'admin' && password === '123456') {
    const token = jwt.sign({ username }, SECRET, { expiresIn: '1h' })
    res.json({ token })
  } else {
    res.status(401).json({ message: '登录失败' })
  }
})

// 授权接口
app.get('/profile', (req, res) => {
  const auth = req.headers.authorization
  if (!auth) return res.status(401).json({ message: '缺少token' })

  const token = auth.split(' ')[1]
  try {
    const decoded = jwt.verify(token, SECRET)
    res.json({ msg: '成功访问!', user: decoded })
  } catch (err) {
    res.status(403).json({ msg: 'Token无效或过期' })
  }
})

app.listen(3000, () => {
  console.log('http://localhost:3000 启动成功')
})

🍪 JWT 和 Cookie 的正面对决:谁更适合我?

很多刚接触前后端认证的同学都会问:

❓“JWT 和 Cookie 是不是一回事?”
❓“我项目该用哪个?”

回答:不是一回事!但可以搭配使用。

我们来看下它们的区别和用途:

对比维度JWTCookie
定义一种令牌规范浏览器内建的存储机制
储存位置可存 localStorage、cookie 等浏览器自动维护
用途身份令牌(认证、权限控制)存储小数据(sessionId、偏好设置)
大小限制~7kb(Base64)每个 cookie 限 ~4kb
跨域限制默认不带 cookie,需手动设置跨域默认不发送,需要配置 withCredentials
安全性容易被 XSS 获取(如果存在 localStorage)易受 CSRF 攻击,需搭配 SameSite+HttpOnly
服务端压力无状态,服务端无存储压力需要 session 存储,服务端开销更大

✅ 合理搭配最佳实践:

模式实现方案
Token 存在 localStorage易开发,适合移动端 / 简单项目
Token 存在 HttpOnly Cookie安全性更高,适合生产环境
Cookie 中放 SessionID,后端维护状态传统 Web 模式,适合老项目或服务端渲染

🧠 总结升级版:JWT ≠ Cookie,它们可以并肩作战!

JWT 更像是一个“内容丰富的身份证”,而 Cookie 更像是“操作系统的口袋”。你可以选择:

  • 开发速度优先 → JWT + localStorage
  • 安全性优先 → JWT + HttpOnly Cookie
  • SSR 项目 / 老系统 → Cookie + Session

🔥 实际开发中,你得注意的“坑”

  1. Token 太大了?
    不要把用户资料全写进去,只放最小的 userId 或权限等级

  2. Token 过期怎么办?
    expiresIn 设置时间,配合刷新令牌(Refresh Token)策略更稳妥

  3. 退出登录怎么处理?
    JWT 没有内建注销机制,常见方式是:

    • 设置黑名单(Redis 存储无效 token)
    • 缩短有效期 + Refresh Token 控制生命周期
  4. 要不要放在 localStorage?

    • localStorage: 简单易用但不防 XSS
    • cookie + HttpOnly: 安全性更高(推荐)

🧭 JWT 在前端项目中的应用场景

  • React / Vue 项目用户登录认证
  • 后台管理系统权限控制
  • App 小程序等移动端请求授权
  • 与后端分离的 API 接口认证

🧾 总结

JWT 是一把钥匙,解决了前后端分离后的“我是谁”问题:

✅ 轻量、无状态
✅ 易于分布式部署
✅ 开发简单,上手快


🧑‍🎓 最后一句话总结

以前是“谁登录谁知道”,
现在是“你拿 token,大家都知道你是谁”。

JWT,就像是现代前端江湖中的一枚通行令牌,在微服务横行、前后端分离的大环境下,它以简洁而优雅的方式,解决了“你是谁”与“你是否有权”的千古难题。它无须依赖服务端状态,却能守住数据边界的底线;它可以轻巧存于 localStorage,也可以悄然藏身于 HttpOnly Cookie,既能追求速度,也能坚守安全。从身份认证到权限控制,从请求头到签名算法,这不仅是一次技术的实践,更是开发者与系统信任机制之间的一次深度握手。学会 JWT,不只是为了实现一个登录功能,而是你构建安全、高效、可扩展应用体系的第一步。


如果你觉得文章有帮助,欢迎点赞 + 收藏 + 评论~
你的三连,是我写作的最大动力 🧡