Node.js中Post请求后出现401未授权错误的解决方法
问题:新注册账号登录返回401未授权错误
本地环境下登录注册功能完全正常:注册账号数据可存入数据库,重复注册会提示账号已存在,本地创建的账号能正常登录;但新注册的账号在Render部署环境登录时会返回401(未授权)错误。已在本地添加包含Token的.env文件,且在Render平台配置了对应的环境变量。
相关代码
server.js
const express = require('express'); const app = express(); const path = require('path'); const cors = require('cors'); const corsOptions = require('./config/corsOptions'); const { logger } = require('./middleware/logEvents'); const errorHandler = require('./middleware/errorHandler'); const verifyJWT = require('./middleware/verifyJWT'); const cookieParser = require('cookie-parser'); const credentials = require('./middleware/credentials'); const PORT = process.env.PORT || 3500; // custom middleware logger app.use(logger); // Handle options credentials check - before CORS! // and fetch cookies credentials requirement app.use(credentials); // Cross Origin Resource Sharing app.use(cors(corsOptions)); // built-in middleware to handle urlencoded form data app.use(express.urlencoded({ extended: false })); // built-in middleware for json app.use(express.json()); //middleware for cookies app.use(cookieParser()); //serve static files app.use('/', express.static(path.join(__dirname, '/public'))); // routes app.use('/', require('./routes/root')); app.use('/register', require('./routes/register')); app.use('/auth', require('./routes/auth')); app.use('/refresh', require('./routes/refresh')); app.use('/logout', require('./routes/logout')); app.use(verifyJWT); app.use('/employees', require('./routes/api/employees')); app.all('*', (req, res) => { res.status(404); if (req.accepts('html')) { res.sendFile(path.join(__dirname, 'views', '404.html')); } else if (req.accepts('json')) { res.json({ "error": "404 Not Found" }); } else { res.type('txt').send("404 Not Found"); } }); app.use(errorHandler); app.listen(PORT, () => console.log(`Server running on port ${PORT}`));
auth.js
const express = require('express'); const router = express.Router(); const authController = require('../controllers/authController'); router.post('/', authController.handleLogin); module.exports = router;
authController.js
const usersDB = { users: require('../model/users.json'), setUsers: function (data) { this.users = data; }, }; const bcrypt = require('bcrypt'); const jwt = require('jsonwebtoken'); require('dotenv').config(); const fsPromises = require('fs').promises; const path = require('path'); const handleLogin = async (req, res) => { const { user, pwd } = req.body; if (!user || !pwd) return res .status(400) .json({ message: 'Username and password are required.' }); const foundUser = usersDB.users.find((person) => person.username === user); if (!foundUser) return res.sendStatus(401); //Unauthorized // evaluate password const match = await bcrypt.compare(pwd, foundUser.password); if (match) { const roles = Object.values(foundUser.roles).filter(Boolean); // create JWTs const accessToken = jwt.sign( { UserInfo: { "username": foundUser.username, roles: roles, }, }, process.env.ACCESS_TOKEN_SECRET, { expiresIn: '30s' } ); const refreshToken = jwt.sign( { "username": foundUser.username }, process.env.REFRESH_TOKEN_SECRET, { expiresIn: '1d' } ); // Saving refreshToken with current user const otherUsers = usersDB.users.filter( (person) => person.username !== foundUser.username ); const currentUser = { ...foundUser, refreshToken }; usersDB.setUsers([...otherUsers, currentUser]); await fsPromises.writeFile( path.join(__dirname, '..', 'model', 'users.json'), JSON.stringify(usersDB.users) ); res.cookie('jwt', refreshToken, { httpOnly: true, sameSite: 'None', secure: true, maxAge: 24 * 60 * 60 * 1000, }); res.json({ accessToken }); } else { res.sendStatus(401); } }; module.exports = { handleLogin };
排查方向与解决方案
1. 文件系统写入权限问题(核心原因)
Render平台的文件系统是临时且只读的(除指定持久化目录外),你的代码在authController.js中尝试写入users.json文件:
await fsPromises.writeFile( path.join(__dirname, '..', 'model', 'users.json'), JSON.stringify(usersDB.users) );
这会导致新注册用户的信息无法持久化,登录时从users.json中找不到新用户,直接返回401。
解决方法:
- 替换为正式数据库(如PostgreSQL、MongoDB),Render官方支持这些数据库服务;
- 若仅临时测试,可配置Render的持久存储卷挂载到
model目录,但该方案不适合生产环境。
2. Cookie属性配置验证
线上环境中secure: true要求请求必须为HTTPS,如果前端请求使用HTTP(或本地测试时的HTTP),Cookie无法被正确设置。不过你本地正常,线上新用户登录401更可能是文件系统问题,但可临时注释secure: true验证。
3. 环境变量一致性检查
确认Render平台的环境变量名称与代码中完全一致:
- 检查
ACCESS_TOKEN_SECRET和REFRESH_TOKEN_SECRET的拼写、大小写是否匹配; - 可临时添加日志
console.log(process.env.ACCESS_TOKEN_SECRET)验证变量是否加载成功(注意不要泄露密钥)。
4. 用户数据存在性验证
在Render平台通过控制台或日志查看users.json内容,确认新注册用户是否被写入文件。
内容的提问来源于stack exchange,提问作者Krystian Owczarek
相关产品推荐
相关产品推荐

