引言:为什么要登录凭证
还记得小时候进游乐场要盖章吗?盖了章,随时进出没人拦你。Web世界也一样,用户登录后,服务器要给你个“通行证”。JWT(JSON Web Token)就像发你一张防伪二维码,走哪都能扫,轻便又安全!
一、JWT是什么?
JWT,全称JSON Web Token,是一种基于JSON的开放标准(RFC 7519),用于在网络应用环境间安全地传递声明信息。说人话:它就是一张数字签名的“身份证”,你带着它,服务器就能确认你是谁。
1.1 结构大揭秘
JWT长这样:
header.payload.signature
- Header:声明类型(JWT)和算法(如HS256)
- Payload:装你要传的信息(比如用户ID、昵称、权限等)
- Signature:用密钥签名,防篡改
举个栗子:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidXNlcm5hbWUiOiJqYWNrIiwiaWF0IjoxNjg4ODg4ODg4fQ.abc123xyz456
是不是像极了超市小票后面那串神秘字符?
二、JWT在项目中的实战应用与代码详解
2.1 登录流程全解析
- 用户输入用户名和密码,发起登录请求
- 服务器校验通过后,生成JWT(短token+长token)
- 前端收到token,存到localStorage
- 之后每次请求都带上token,后端校验通过才放行
- token过期?用长token刷新短token,无感体验,用户丝滑如初恋!
2.2 代码实战逐行详解
2.2.1 登录接口(后端)
router.post('/login', async (ctx) => {
// 1. 获取请求体中的账号和密码
let { username, password } = ctx.request.body
// 2. 防SQL注入,转义特殊字符
username = escape(username)
password = escape(password)
try {
// 3. 查询数据库,校验账号密码
const res = await userLogin(username, password)
if (res.length) {
// 4. 组装用户数据
let data = { id: res[0].id, username: res[0].username, nickname: res[0].nickname, createTime: res[0].create_time }
// 5. 生成短token(1小时有效)和长token(7天有效)
const access_token = sign(data, '1h')
const refresh_token = sign(data, '7d')
// 6. 返回token和用户信息
ctx.body = { code: '1', msg: '登录成功', data, access_token, refresh_token }
} else {
ctx.body = { code: '0', msg: '账号或密码错误', data: {} }
}
} catch (error) {
ctx.body = { code: '-1', msg: '服务器异常', data: error }
}
})
重点解析:
escape函数防止SQL注入,安全第一!sign方法用密钥对用户数据签名,生成JWT。- 返回两个token,短token用于日常鉴权,长token用于刷新。
2.2.2 前端登录逻辑
axios.post('/user/login', values).then(res => {
toast.success('登录成功')
// 1. 保存短token和长token到localStorage
localStorage.setItem('access_token', res.access_token)
localStorage.setItem('refresh_token', res.refresh_token)
// 2. 保存用户信息
localStorage.setItem('userInfo', JSON.stringify(res.data))
// 3. 跳转到主页面
navigate('/noteClass')
})
重点解析:
- 登录成功后,token和用户信息本地持久化,页面跳转。
- 这样后续所有请求都能自动带上token。
2.2.3 请求拦截与token自动刷新
axios.interceptors.request.use(request => {
// 1. 每次请求自动携带access_token
const token = localStorage.getItem('access_token')
if (token) {
request.headers.Authorization = token
}
return request
})
axios.interceptors.response.use(
(response) => { /* ... */ },
(res) => {
// 2. 如果短token失效,自动用refresh_token刷新
if (res.response.status === 401) {
const refresh_token = localStorage.getItem('refresh_token')
if (refresh_token) {
axios.post('./user/refresh', { refresh_token }).then(res => {
if (res.code === '1') {
// 3. 刷新成功,更新token并重发原请求
localStorage.setItem('access_token', res.access_token)
localStorage.setItem('refresh_token', res.refresh_token)
originalRequest.headers.Authorization = res.access_token
return axios(originalRequest)
}
})
} else {
toast.error('请先登录');
setTimeout(() => { window.location.href = '/login'; }, 2000);
}
}
}
)
重点解析:
- 请求拦截器自动加token,响应拦截器自动处理token过期。
- 刷新机制让用户体验无缝衔接。
2.2.4 后端token校验中间件
function verify() {
return async (ctx, next) => {
// 1. 从请求头获取token
const token = ctx.headers.authorization
if (token) {
try {
// 2. 校验token有效性
const decoded = jwt.verify(token, '666')
if (decoded.id) {
// 3. 校验通过,挂载用户ID,放行
ctx.userId = decoded.id
await next()
}
} catch (error) {
// 4. token无效,返回401
ctx.status = 401
ctx.body = { code: '0', msg: '登录失效' }
}
} else {
ctx.status = 401
ctx.body = { code: '0', msg: '请先登录' }
}
}
}
重点解析:
- 校验token合法性,防止未授权访问。
- 校验失败直接返回401,安全兜底。
2.2.5 注册接口安全细节
router.post('/register', async (ctx) => {
let { nickname, username, password } = ctx.request.body
if (!nickname || !username || !password) {
ctx.body = { code: '0', msg: '账号密码昵称不能为空' }
}
// 1. 所有字段escape防注入
username = escape(username)
nickname = escape(nickname)
password = escape(password)
// 2. 检查账号是否已存在
// 3. 数据库写入
// ...
})
重点解析:
- 注册同样要防注入,所有字段都escape。
- 账号唯一性校验,防止重复注册。
三、JWT的优缺点大起底
优点
- 无需服务器存储会话,扩展性强,适合分布式架构
- 前后端分离,移动端、Web端通用
- 支持自定义载荷,灵活扩展
缺点
- token一旦泄露,风险极大(所以要用HTTPS!)
- 无法主动失效(除非黑名单机制)
- 载荷过大影响性能
四、实战Tips与安全建议
- 签名密钥要复杂,别用123456或password(不然黑客都笑了😀)
- token只走HTTPS,明文传输等于裸奔
- 设置合理过期时间,短token+长token组合拳
- 敏感信息别放payload,JWT不是保险箱
- 刷新机制要完善,体验和安全两手抓
- escape防注入,注册和登录都要做!
总结:JWT让Web认证更优雅
JWT就像你出门带的身份证,轻便、通用、还能防伪。配合合理的刷新机制和安全措施,既能提升用户体验,又能保证系统安全。希望本文能让你对JWT有更深刻的理解,项目实战也能用得得心应手!
(๑•̀ㅂ•́)و✧
既然已经看到这了吧, 请动动发财小手, 点点小赞吧👍