小白也能懂的 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 怎么工作?就三步
整个认证流程特别简单,跟你去银行办事差不多:
- "办卡"(登录) :你带身份证(用户名 / 密码)去银行(服务器),银行核实后,给你一张银行卡(JWT Token);
- "用卡"(发请求) :之后你每次去银行办事(访问接口),都得带上这张卡(在请求头里带 Token);
- "验卡"(验证) :银行看一眼你的卡是不是真的、有没有过期(服务器验证 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
-
打开 Postman,选择 "POST" 方法,输入地址:
http://localhost:3000/login
; -
点击 "Body",选择 "raw",再选 "JSON" 格式;
-
输入下面的内容(测试账号密码):
json
json{ "username": "testuser", "password": "testpass" }
-
点击 "Send",右边会返回结果,里面有个
token
字段,把这串长长的字符复制下来(这就是你的 Token)。
第二步:用 Token 访问受保护接口
-
新建一个请求,选择 "GET" 方法,输入地址:
http://localhost:3000/profile
; -
点击 "Headers",添加一行:
- Key:写
Authorization
(注意首字母大写) - Value:写
Bearer 你刚才复制的Token
(注意 "Bearer" 后面有个空格,别漏了)
- Key:写
-
点击 "Send",右边会返回你的个人信息,说明认证成功了!
如果没带 Token,或者 Token 错了,右边会返回 "Token 有问题",这就对了 ------ 说明我们的认证起作用了。
四、JWT 认证的优缺点:别光用,得知道好坏
优点:为啥大家都用 JWT?
- 服务器不用记东西:服务器不用存你的会话信息,不管多少人登录,都不影响性能,适合多台服务器一起用(比如淘宝的服务器有几百台,总不能每台都记你的信息吧);
- 跨域方便:Cookie 跨域特别麻烦,Token 直接放请求头里,不管前端后端在不在一个域名下,都能正常用;
- 简单轻量:Token 字符串不长,传起来快,不占带宽。
缺点:别踩坑!
- Token 不能主动作废:比如你登录后退出了,但 Token 没过期,别人拿到你的 Token 还是能访问接口。解决办法是搞个 "黑名单",把退出的 Token 存进去,服务器验证前先查黑名单;
- 不能存敏感信息:Payload 部分是 Base64 编码,不是加密,随便找个 Base64 解码工具就能解开,所以绝对不能存密码、手机号这些隐私数据;
- 有效期难平衡:有效期设太长,不安全;设太短,用户老得重新登录,体验差。解决办法是搞 "刷新 Token"------ 短 Token(1 小时)用来访问接口,长 Token(7 天)用来换短 Token,用户不用频繁登录。
正式项目里要注意的点(避坑指南)
- 密钥要安全:用随机生成的长字符串(比如 32 位),存在环境变量里,别写代码里;
- 密码要哈希 :用
bcrypt
工具处理密码,别存明文; - 用 HTTPS:Token 在网上传的时候,要用 HTTPS 加密,不然别人能偷你的 Token;
- 加权限控制 :比如管理员和普通用户看到的内容不一样,可以在 Token 里加个
role
字段(比如"role":"admin"
),接口里判断角色给不同数据; - 处理 Token 过期:前端要监听 401 错误,Token 过期了就跳登录页,或者用刷新 Token 自动续期。
五、总结
其实 JWT 认证没那么复杂,核心就是 "发 Token - 带 Token - 验 Token" 这三步。今天咱们从原理讲到代码,再到测试,小白也能跟着做出来。
正式项目里,重点关注安全问题:密钥要藏好、密码要哈希、用 HTTPS、处理 Token 过期。只要把这些细节做好,JWT 就能帮你安全地识别用户身份,让你的项目更靠谱。
希望这篇文章能帮你搞懂 Token 认证,下次再遇到类似需求,就能轻松搞定啦!