因为客户端是Electron
做得,所以里面集成了Express
和SocketIO
做前端基础服务,最近服务端要改成前端对登录做JWT
,他们只负责做存取,让我们来复习一下JWT
基础以及如何在express
下实现JWT
认证。
JWT 是什么
JWT(JSON Web Token)
是一种开放标准(RFC 7519),用于在网络应用环境中以紧凑的方式安全地传递信息。它是基于 JSON
格式的,可以在客户端和服务器之间进行传输。
主要特点:
- 自包含:
JWT
可以携带用户信息(如用户 ID、角色等),无需查询数据库,减少请求次数。 - 安全性:
JWT
可以使用签名(如 HMAC SHA256)来防止信息篡改。只有拥有密钥的服务器才能生成有效的JWT
。 - 跨域认证:
JWT
可以用于不同域之间的认证,适合RESTful API
和单页面应用(SPA)。 - 可扩展性:可以轻松地在负载中添加自定义声明,以满足不同需求。
结构 - 一个 JWT 通常由三部分组成:
头部(Header):指定令牌的类型(通常是 “JWT”)和所使用的签名算法(如 HMAC SHA256)。
{
"alg": "HS256",
"typ": "JWT"
}
有效载荷(Payload):包含声明(claims),如用户信息和其他元数据。可以是预定义的(如 iss、exp、sub 等)或自定义的。
{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022
}
签名(Signature):使用头部和有效载荷进行编码,并使用密钥进行签名。这样可以确保令牌的完整性。
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
代码
const express = require('express');
const jwt = require('jsonwebtoken');
const crypto = require('crypto');
const md5 = crypto.createHash('md5');
require('dotenv').config();
const app = express();
app.use(express.json());
const SECRET_KEY = process.env.SECRET_KEY;
app.post('/login', (req, res) => {
const { username, password } = req.body;
// 通过MD5问服务端查询接口看密码对不对
const token = jwt.sign({ username }, SECRET_KEY, { expiresIn: '1h' });
res.json({ token });
});
function authenticateToken(req, res, next) {
const token = req.headers['authorization']?.split(' ')[1];
if (!token) return res.sendStatus(401);
jwt.verify(token, SECRET_KEY, (err, user) => {
if (err) return res.sendStatus(403);
req.user = user;
next();
});
}
app.get('/protected', authenticateToken, (req, res) => {
res.json({ message: '这是一个需要登录的保护的接口', user: req.user });
});
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Server is running on http://localhost:${PORT}`);
});
然后前端大概这么搞
// 登录
async function login(username, password) {
const response = await fetch('http://localhost:3000/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ username, password }),
});
if (response.ok) {
const data = await response.json();
const token = data.token;
// 将 token 存储在本地存储中(或 Cookie)
localStorage.setItem('jwt', token);
console.log('登录成功!', token);
} else {
console.error('登录失败');
}
}
// 使用
async function accessProtectedRoute() {
const token = localStorage.getItem('jwt'); // 从本地存储中获取 JWT
const response = await fetch('http://localhost:3000/protected', {
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`, // 将 JWT 作为 Bearer token 添加到请求头
},
});
if (response.ok) {
const data = await response.json();
console.log('受保护的内容:', data);
} else {
console.error('不让用啊');
}
}