本文提供了从零开始的JWT用户校验课程,详细介绍了JWT的概念、工作原理和优势,涵盖生成、验证JWT以及JWT在用户认证和授权中的应用案例。此外,文章还讨论了JWT的安全使用方法和常见问题的解决方案。JWT 用户校验课程旨在帮助开发者全面掌握JWT技术。
JSON Web Token(JWT)是一种开放标准(RFC 7519),用于在网络应用环境中传输对称加密或非对称加密的信息。JWT 主要用于解决现有的一些认证和授权问题,它能够安全地传输用户信息,而无需频繁地调用服务器来验证用户身份。
JWT 由三部分组成,它们之间用点(.
)分隔:
JWT 的工作原理基于以下步骤:
Authorization
字段发送给服务器。JWT 的主要优势包括:
JWT 的应用场景包括:
为了生成和验证 JWT,你需要在你的开发环境中安装一些必要的库。这里以 Node.js 进行演示。
jsonwebtoken
库:
npm install jsonwebtoken
为了更好地进行 JWT 的开发,你需要设置一个简单的 Node.js 服务器,并确保它能够生成和验证 JWT。
mkdir jwt-course cd jwt-course
npm init -y
安装依赖:
npm install express jsonwebtoken
创建服务器文件:
创建一个 server.js
文件,并在其内部设置一个简单的 Express 服务器。
const express = require('express'); const jwt = require('jsonwebtoken'); const app = express(); const port = 3000; const secret = 'mysecretkey'; // 定义密钥 app.listen(port, () => { console.log(`Server running on port ${port}`); });
在服务器中,你需要写一段代码来生成 JWT。该代码将包含用户的 ID、用户名等信息,并使用私钥对 JWT 进行签名。
const secret = 'mysecretkey';
app.post('/login', (req, res) => { const user = { id: 1, username: 'testuser' }; const token = jwt.sign(user, secret, { expiresIn: '1h' }); res.json({ token }); });
为了确保 JWT 工作正常,你需要写一段代码来解析并验证 JWT。
app.get('/protected', (req, res) => { const token = req.headers.authorization.split(' ')[1]; if (!token) { return res.status(401).json({ message: 'No token provided' }); } jwt.verify(token, secret, (err, decoded) => { if (err) { return res.status(401).json({ message: 'Invalid token' }); } res.json({ message: `Welcome ${decoded.username}` }); }); });
当客户端向服务器发送请求时,它通常会将 JWT 附加在请求头中。你需要在服务器端接收并解析这些 JWT。
const token = req.headers.authorization.split(' ')[1];
jsonwebtoken
库的 verify
方法验证 JWT。
jwt.verify(token, secret, (err, decoded) => { if (err) { return res.status(401).json({ message: 'Invalid token' }); } // JWT 有效,继续处理请求 });
const user = decoded; console.log(user); // { id: 1, username: 'testuser' }
使用 JWT 进行用户认证是其最常见也是最重要的应用场景。以下是一个简单的示例,展示了如何使用 JWT 实现用户登录和访问受保护资源的功能。
app.post('/login', (req, res) => { const user = { id: 1, username: 'testuser' }; const token = jwt.sign(user, secret, { expiresIn: '1h' }); res.json({ token }); });
app.get('/protected', (req, res) => { const token = req.headers.authorization.split(' ')[1]; if (!token) { return res.status(401).json({ message: 'No token provided' }); } jwt.verify(token, secret, (err, decoded) => { if (err) { return res.status(401).json({ message: 'Invalid token' }); } res.json({ message: `Welcome ${decoded.username}` }); }); });
在前后端交互中,JWT 可以用来传递用户信息,从而实现无状态的认证和授权。以下是一个简单的例子,展示了前端如何使用 JWT 访问后端受保护的资源。
fetch('/protected', { method: 'GET', headers: { 'Authorization': 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw1' }) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error(error));
const token = req.headers.authorization.split(' ')[1]; jwt.verify(token, secret, (err, decoded) => { if (err) { return res.status(401).json({ message: 'Invalid token' }); } console.log(decoded); // 解析后的用户信息 res.json({ message: `Welcome ${decoded.username}` }); });
JWT 通常会有一个过期时间(例如 1 小时),当 JWT 过期时,客户端需要重新获取一个新的 JWT。这里介绍一种常见的处理过期 JWT 的方法。
前端处理:前端在每次请求时,检查 JWT 是否过期,并在过期时重新获取新的 JWT。
function checkTokenExpiration(token) { const decoded = jwt.decode(token); const currentTime = Math.floor(Date.now() / 1000); return decoded.exp > currentTime; } const token = localStorage.getItem('token'); if (!token || !checkTokenExpiration(token)) { // 重新获取 JWT fetch('/login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ username: 'testuser', password: 'testpassword' }) }) .then(response => response.json()) .then(data => { localStorage.setItem('token', data.token); // 使用新获取的 JWT 继续请求 }); }
jwt.verify(token, secret, (err, decoded) => { if (err && err.name === 'TokenExpiredError') { return res.status(401).json({ message: 'Token expired' }); } // JWT 有效,继续处理请求 });
为了确保 JWT 的安全性,你需要遵循以下几个原则:
// 设置 HTTP-only Cookie res.cookie('token', token, { httpOnly: true, secure: true, // 生产环境中一定要设置为 true maxAge: 3600000 // 过期时间 1 小时 }); // 从前端获取 Cookie 中的 JWT document.cookie.split('; ').forEach(cookie => { const [name, value] = cookie.split('='); if (name === 'token') { console.log(value); } });
在使用 JWT 过程中,可能会遇到各种问题,以下是一些排查和调试技巧: