如何基于登录用户自定义Node.js Express API端点URL?
实现基于登录用户的Express API路由控制
要实现localhost:8080/api/v1/user/${username}这种自定义端点,并确保用户仅能访问自身账户数据,核心思路是先认证获取当前用户信息,再校验URL参数与当前用户的一致性。以下是具体实现步骤和代码示例:
核心步骤
- 用户认证:通过JWT验证用户身份,将登录用户信息挂载到请求对象上。
- 权限校验中间件:对比URL参数中的
username和当前登录用户的username,不一致则拒绝访问。 - 重构路由:将查询、更新、删除等接口改为
/:username结构,并挂载认证和权限校验中间件。
代码实现
1. 安装依赖
先安装所需包:
npm install express jsonwebtoken dotenv
2. 认证与权限校验中间件
创建middleware/auth.js:
const jwt = require('jsonwebtoken'); // 解析请求头中的JWT令牌,获取当前用户信息 const authenticateUser = (req, res, next) => { const authHeader = req.headers.authorization; if (!authHeader || !authHeader.startsWith('Bearer ')) { return res.status(401).json({ message: '未提供有效认证令牌' }); } const token = authHeader.split(' ')[1]; try { const decoded = jwt.verify(token, process.env.JWT_SECRET); req.user = decoded; // 将用户信息挂载到req对象 next(); } catch (err) { return res.status(401).json({ message: '认证令牌无效或已过期' }); } }; // 权限校验:确保用户只能访问自己的资源 const authorizeOwnResource = (req, res, next) => { const { username } = req.params; if (req.user.username !== username) { return res.status(403).json({ message: '无权访问该资源' }); } next(); }; module.exports = { authenticateUser, authorizeOwnResource };
3. 用户路由配置
创建routes/user.js:
const express = require('express'); const jwt = require('jsonwebtoken'); const { authenticateUser, authorizeOwnResource } = require('../middleware/auth'); const router = express.Router(); // 注册接口(无需认证) router.post('/auth/register', (req, res) => { const { username, password, email } = req.body; // 此处省略数据库创建用户的逻辑(如加密密码、存储用户信息) const token = jwt.sign({ username }, process.env.JWT_SECRET, { expiresIn: '1d' }); res.status(201).json({ message: '注册成功', token }); }); // 登录接口(无需认证) router.post('/auth/login', (req, res) => { const { username, password } = req.body; // 此处省略数据库验证用户名密码的逻辑 const token = jwt.sign({ username }, process.env.JWT_SECRET, { expiresIn: '1d' }); res.json({ message: '登录成功', token }); }); // 获取当前用户信息(需要认证+权限校验) router.get('/:username', authenticateUser, authorizeOwnResource, (req, res) => { // 此处省略从数据库查询用户信息的逻辑,用req.user.username作为查询条件 res.json({ username: req.user.username, email: 'user@example.com', createdAt: '2024-01-01' }); }); // 更新当前用户信息(需要认证+权限校验) router.put('/:username', authenticateUser, authorizeOwnResource, (req, res) => { const { email, password } = req.body; // 此处省略数据库更新用户信息的逻辑,用req.user.username作为查询条件 res.json({ message: '用户信息更新成功', user: { username: req.user.username, email } }); }); // 删除当前用户账户(需要认证+权限校验) router.delete('/:username', authenticateUser, authorizeOwnResource, (req, res) => { // 此处省略数据库删除用户的逻辑,用req.user.username作为查询条件 res.json({ message: '账户已成功删除' }); }); module.exports = router;
4. 主应用入口
创建app.js:
const express = require('express'); const userRouter = require('./routes/user'); require('dotenv').config(); const app = express(); app.use(express.json()); // 解析JSON请求体 // 挂载用户路由 app.use('/api/v1/user', userRouter); const PORT = process.env.PORT || 8080; app.listen(PORT, () => { console.log(`服务器运行在 http://localhost:${PORT}`); });
5. 环境变量配置
创建.env文件:
JWT_SECRET=your_secure_jwt_secret_key_here PORT=8080
关键说明
- 注册和登录接口保留原有
/auth路径,因为这两个操作不需要用户预先登录。 - 所有涉及用户自身资源的操作(查询、更新、删除)都必须经过
authenticateUser和authorizeOwnResource中间件,确保只有用户本人能访问对应的/:username端点。 - 即使恶意用户构造其他用户名的URL(如
/api/v1/user/anotheruser),权限校验中间件会对比当前登录用户的username,不一致则返回403禁止访问。
内容的提问来源于stack exchange,提问作者Prashant Singh
相关产品推荐
相关产品推荐

