小白也能懂的 Token 认证:从原理到实战,用 Express 手把手教你做

小白也能懂的 Token 认证:从原理到实战,用 Express 手把手教你做

前后端分离的项目里,怎么确定 "你就是你"?比如你登录后想查看个人信息,服务器得知道 "现在发请求的人,确实是刚登录成功的那个用户"。以前用 Cookie-Session 的方式,跨域的时候特别麻烦,而 Token 认证就没这问题,现在几乎成了主流。今天就用大白话讲清楚 JWT(最常用的 Token 格式)是啥,再结合 Express 代码,教你搭一个能直接用的认证系统。

一、先搞懂:JWT 到底是个啥?

简单说,JWT 就是一串 "加密的身份小纸条"。服务器给你发这张纸条,你之后每次找服务器要东西,都得带上它 ------ 服务器不用记你的信息,只要看这张纸条对不对,就知道你是不是合法用户。

1. JWT 长啥样?三段式字符串而已

一个完整的 JWT 是这样的,用.分成三部分,比如:

plaintext

复制代码
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjEsInVzZXJuYW1lIjoidGVzdHVzZXIiLCJpYXQiOjE3MTY2NTM0MDksImV4cCI6MTcxNjY1NzAwOX0.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

这三部分各有各的用,咱们用 "快递包裹" 打比方,一下子就懂了:

部分 大白话作用 里面存啥(举例子) 能不能随便看?
Header(头部) 告诉大家 "我是 JWT,用 XX 方法加密的" {"alg":"HS256","typ":"JWT"} 能(Base64 编码,不是加密)
Payload(载荷) 存你的身份信息(比如 "你是谁,ID 多少") {"userId":1,"username":"testuser"} 能(同上,千万别存密码
Signature(签名) 防止纸条被篡改(服务器的 "防伪标志") 用密钥算出来的加密串(外人解不开) 不能(核心防伪部分)

2. JWT 怎么工作?就三步

整个认证流程特别简单,跟你去银行办事差不多:

  1. "办卡"(登录) :你带身份证(用户名 / 密码)去银行(服务器),银行核实后,给你一张银行卡(JWT Token);
  2. "用卡"(发请求) :之后你每次去银行办事(访问接口),都得带上这张卡(在请求头里带 Token);
  3. "验卡"(验证) :银行看一眼你的卡是不是真的、有没有过期(服务器验证 Token),没问题就给你办事(返回数据),有问题就赶你走(返回 401 错误)。

二、动手做:用 Express 搭 JWT 认证系统

接下来咱们照着代码一步步做,不用怕,都是基础操作。需要的工具就三个:express(搭服务器)、jsonwebtoken(生成 Token)、express-jwt(验证 Token)。

1. 先准备环境:装依赖

先建个文件夹,打开命令行,输入这两句,把需要的工具装好:

bash

csharp 复制代码
# 初始化项目(生成package.json,不用管它是啥,装依赖要用)
npm init -y

# 装核心工具:express(服务器)、jsonwebtoken(造Token)、express-jwt(验Token)
npm install express jsonwebtoken express-jwt

2. 核心代码拆解:从配置到接口

咱们把代码分成几块,每块都讲清楚干啥用的,跟着写就行。

第一步:搭好服务器架子,配基础设置

先把服务器启动起来,再配置好 "读 JSON 数据" 的功能(不然收不到前端发的用户名密码):

javascript

ini 复制代码
// 把装的工具引进来
const express = require('express');
const jwt = require('jsonwebtoken');
const { expressjwt: expressJWT } = require('express-jwt');

// 初始化服务器
const app = express();

// 关键:能读懂前端发的JSON格式数据(比如用户名密码)
app.use(express.json());

// 配置两个重要常量:
const SECRET_KEY = 'your-secret-key-keep-safe'; // 服务器的"密钥",验Token全靠它
const ALGORITHM = 'HS256'; // 加密方法(不用改,就用这个)

⚠️ 重点提醒SECRET_KEY 就像你家的钥匙,绝对不能写死在代码里!正式项目里要存在 "环境变量" 里(比如用 dotenv 工具),不然别人拿到代码,就能伪造你的 Token 了。

第二步:配 "全局验 Token" 中间件

这个中间件的作用是:所有接口默认都要验 Token,除了登录接口(总不能登录也要 Token 吧,不然永远登不上)。

javascript

less 复制代码
app.use(expressJWT({
  secret: SECRET_KEY, // 用刚才的密钥验Token
  algorithms: [ALGORITHM] // 用刚才的加密方法
}).unless({ path: ['/login'] })); // 排除/login接口,不用验Token

简单说:以后不管访问/profile还是/dashboard,服务器都会先看你带的 Token 对不对;只有访问/login,才不用验。

第三步:写登录接口:给用户发 Token

登录是唯一不用验 Token 的接口,作用就是 "核实用户名密码,对了就发 Token"。

javascript

javascript 复制代码
// 模拟数据库(正式项目要连MySQL、MongoDB这些真数据库)
const users = [
  { id: 1, username: 'testuser', password: 'testpass' } // 测试账号
];

// 登录接口:POST请求(前端发数据过来)
app.post('/login', (req, res) => {
  // 1. 从前端拿用户名和密码(req.body就是前端发的JSON数据)
  const { username, password } = req.body;
  
  // 2. 查"数据库",看有没有这个用户,密码对不对
  const user = users.find(u => u.username === username && u.password === password);
  if (!user) { // 没找到用户,或密码错了
    return res.status(401).send('用户名或密码错啦!');
  }
  
  // 3. 密码对了,生成Token
  const token = jwt.sign(
    // 第一部分:存用户身份信息(别存密码!谁都能解开)
    { userId: user.id, username: user.username },
    // 第二部分:用服务器密钥加密
    SECRET_KEY,
    // 第三部分:配置(Token有效期1小时,过了就得重新登录)
    { 
      expiresIn: '1h', 
      algorithm: ALGORITHM
    }
  );
  
  // 4. 把Token发给前端
  res.json({
    message: '登录成功!',
    token: token // 前端要把这个Token存起来(比如存在localStorage里)
  });
});

⚠️ 安全提醒 :示例里密码是明文存的,正式项目绝对不能这么干!要先用bcrypt这种工具把密码 "哈希"(变成一串乱码),存数据库里;验证的时候,再用工具把前端传的密码和哈希后的密码比对。

第四步:写受保护的接口:只有带正确 Token 才能访问

这些接口需要验 Token,验过了才能返回数据。而且验过之后,服务器能从 Token 里读出用户信息(比如用户 ID)。

javascript

javascript 复制代码
// 个人资料接口(只有登录后才能看)
app.get('/profile', (req, res) => {
  // req.auth里就是从Token里解析出来的用户信息(userId、username)
  res.json({
    message: '这是你的个人资料页,别人看不了!',
    user: req.auth // 把用户信息返回给前端
  });
});

// 仪表盘接口(同理,需要Token)
app.get('/dashboard', (req, res) => {
  res.json({
    message: '这是你的专属仪表盘',
    user: req.auth,
    data: '只有你能看到的数据(比如你的订单、收藏)'
  });
});
第五步:处理 "Token 验证失败" 的情况

比如 Token 过期了、Token 是伪造的,服务器得告诉前端 "咋回事",不能直接报错。

javascript

javascript 复制代码
app.use((err, req, res, next) => {
  // 如果是Token验证失败的错误
  if (err.name === 'UnauthorizedError') {
    return res.status(401).send({
      message: 'Token有问题!',
      detail: err.message // 具体啥问题(比如"Token过期了""签名不对")
    });
  }
  // 其他服务器错误(比如代码写错了)
  res.status(500).send('服务器出小问题啦,稍后再试~');
});

常见的 Token 错误:

  • jwt expired:Token 过期了,让用户重新登录;
  • invalid signature:Token 是假的,可能有人在搞事;
  • invalid token:Token 格式错了,比如前端没加 "Bearer" 前缀。
第六步:启动服务器,准备测试

最后一步,让服务器跑起来,监听 3000 端口:

javascript

javascript 复制代码
app.listen(3000, () => {
  console.log('服务器跑起来啦!地址:http://localhost:3000');
  console.log('测试步骤:');
  console.log('1. 先登录拿Token:发POST请求到 /login,带 {"username":"testuser","password":"testpass"}');
  console.log('2. 再访问受保护接口:发GET请求到 /profile 或 /dashboard,请求头带 Authorization: Bearer 你的Token');
});

到这里,代码就写完了!接下来咱们测试一下,看看好不好使。

三、测试:用 Postman 实操(小白也会)

Postman 是个测试接口的工具,下载下来打开就行,不用注册。

第一步:登录拿 Token

  1. 打开 Postman,选择 "POST" 方法,输入地址:http://localhost:3000/login

  2. 点击 "Body",选择 "raw",再选 "JSON" 格式;

  3. 输入下面的内容(测试账号密码):

    json

    json 复制代码
    {
      "username": "testuser",
      "password": "testpass"
    }
  4. 点击 "Send",右边会返回结果,里面有个token字段,把这串长长的字符复制下来(这就是你的 Token)。

第二步:用 Token 访问受保护接口

  1. 新建一个请求,选择 "GET" 方法,输入地址:http://localhost:3000/profile

  2. 点击 "Headers",添加一行:

    • Key:写 Authorization(注意首字母大写)
    • Value:写 Bearer 你刚才复制的Token(注意 "Bearer" 后面有个空格,别漏了)
  3. 点击 "Send",右边会返回你的个人信息,说明认证成功了!

如果没带 Token,或者 Token 错了,右边会返回 "Token 有问题",这就对了 ------ 说明我们的认证起作用了。

四、JWT 认证的优缺点:别光用,得知道好坏

优点:为啥大家都用 JWT?

  1. 服务器不用记东西:服务器不用存你的会话信息,不管多少人登录,都不影响性能,适合多台服务器一起用(比如淘宝的服务器有几百台,总不能每台都记你的信息吧);
  2. 跨域方便:Cookie 跨域特别麻烦,Token 直接放请求头里,不管前端后端在不在一个域名下,都能正常用;
  3. 简单轻量:Token 字符串不长,传起来快,不占带宽。

缺点:别踩坑!

  1. Token 不能主动作废:比如你登录后退出了,但 Token 没过期,别人拿到你的 Token 还是能访问接口。解决办法是搞个 "黑名单",把退出的 Token 存进去,服务器验证前先查黑名单;
  2. 不能存敏感信息:Payload 部分是 Base64 编码,不是加密,随便找个 Base64 解码工具就能解开,所以绝对不能存密码、手机号这些隐私数据;
  3. 有效期难平衡:有效期设太长,不安全;设太短,用户老得重新登录,体验差。解决办法是搞 "刷新 Token"------ 短 Token(1 小时)用来访问接口,长 Token(7 天)用来换短 Token,用户不用频繁登录。

正式项目里要注意的点(避坑指南)

  1. 密钥要安全:用随机生成的长字符串(比如 32 位),存在环境变量里,别写代码里;
  2. 密码要哈希 :用bcrypt工具处理密码,别存明文;
  3. 用 HTTPS:Token 在网上传的时候,要用 HTTPS 加密,不然别人能偷你的 Token;
  4. 加权限控制 :比如管理员和普通用户看到的内容不一样,可以在 Token 里加个role字段(比如"role":"admin"),接口里判断角色给不同数据;
  5. 处理 Token 过期:前端要监听 401 错误,Token 过期了就跳登录页,或者用刷新 Token 自动续期。

五、总结

其实 JWT 认证没那么复杂,核心就是 "发 Token - 带 Token - 验 Token" 这三步。今天咱们从原理讲到代码,再到测试,小白也能跟着做出来。

正式项目里,重点关注安全问题:密钥要藏好、密码要哈希、用 HTTPS、处理 Token 过期。只要把这些细节做好,JWT 就能帮你安全地识别用户身份,让你的项目更靠谱。

希望这篇文章能帮你搞懂 Token 认证,下次再遇到类似需求,就能轻松搞定啦!

相关推荐
爱勇宝12 小时前
第 1 章:别把“需求文档”当成真正的需求
前端·后端·程序员
IT_陈寒17 小时前
闭包陷阱让我加了两天班,JavaScript你真行
前端·人工智能·后端
易协同低代码18 小时前
通达OA核心类库TD类深度解析
后端
Gopher_HBo18 小时前
Go语言学习笔记(十八)Gin处理Session
后端
谭光志19 小时前
工具塞满上下文窗口怎么办?深度拆解 AI Agent Tool Search 按需加载实现原理
前端·后端·ai编程
她说..19 小时前
Java 默认值设置方式
java·开发语言·后端·springboot
foggyprojects19 小时前
从0开始,一句话启动AI DataAgent
后端·数据分析·ai编程
郡杰19 小时前
一些基础和问题解决
后端
陈随易20 小时前
前端项目部署只要30秒
前端·后端·程序员
YIAN20 小时前
从零手写文件读取 MCP 服务:一文吃透 Model Context Protocol 全链路通信原理
前端·后端·mcp