当客户端输入已使用的用户名时,为什么我不能向客户端发送特定的 mongoose.js 错误?
Why can’t I send specific mongoose.js errors to the client when they enter a username already in use?
我正致力于在 MongoDB MERN 应用程序中实现自定义错误处理。我也在使用 Mongoose 和 passport-local-mongoose。
当用户注册新帐户时,他们应该会在 chrome 控制台中收到一条特定的错误消息,内容为“用户名已存在”。我知道向用户显示所有服务器错误消息是个坏主意,但我想显示 select 几个。
我试过的链接:
https://github.com/saintedlama/passport-local-mongoose
https://www.geeksforgeeks.org/nodejs-authentication-using-passportjs-and-passport-local-mongoose/
代码如下:
server/controller/auth.js
const { User } = require('../models');
const register = async function (req, res) {
try {
const user = new User({ username: req.body.username });
await user.setPassword(req.body.password);
await user.save();
}
catch (err) {
console.log(`error inside save ${err}`);
res.status(500).send(err);
}
};
const login = async function (req, res) {
//code block under construction
console.log(`login!!!!!`);
};
const logout = function (req, res) {
req.session.destroy();
res.end();
};
exports.login = login;
exports.register = register;
exports.logout = logout;
server/models/User.js
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const passportLocalMongoose = require('passport-local-mongoose');
const userSchema = new Schema({
username: { type: String, unique: true },
password: { type: String}
});
userSchema.plugin(passportLocalMongoose);
const User = mongoose.model('User', userSchema);
module.exports = User;
server/routes/api/auth/index.js
const router = require('express').Router();
const passport = require('../../../config/passport');
const authController = require('../../../controllers/auth');
router.route('/logout').get(authController.logout);
router.route('/register').post(authController.register);
router.use(passport.authenticate('local', {
session: true
}));
// Matches with '/api/auth'
router.route('/login').post(authController.login);
module.exports = router;
server/server.js
const path = require('path');
const express = require('express');
const passport = require('./config/passport');
const mongoose = require('mongoose');
const cors = require('cors');
const session = require('express-session');
const helmet = require('helmet');
const morgan = require('morgan');
const corsOptions = require('./config/cors.js');
const routes = require('./routes');
const { v1: uuidv1 } = require('uuid');
// console.log(uuidv1());
const PORT = process.env.PORT || 3001;
const app = express();
mongoose.connect(process.env.MONGODB_URI || 'mongodb://localhost/puzzlegallery', {
useNewUrlParser: true,
useUnifiedTopology: true,
useCreateIndex: true,
useFindAndModify: false
});
mongoose.set("useCreateIndex", true);
// Define middleware here
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
app.use(helmet({ contentSecurityPolicy: false }));
app.use(session({ secret: 'sassy', resave: false, saveUninitialized: true }));
app.use(passport.initialize());
app.use(passport.session());
app.use(cors(corsOptions));
app.use(morgan('dev'));
app.use(routes);
// for Reactjs ##################
// Serve up static assets (usually on heroku)
if (process.env.NODE_ENV === 'production') {
app.use(express.static('client/build'));
}
// #################################################
if (process.env.NODE_ENV === 'production') {
app.get('*', (_, res) => {
res.sendFile(path.join(__dirname, '../client/build/index.html'));
});
}
app.listen(PORT, (err) => {
if (err) throw err;
console.log(
` Server is Ready and Listening on http://localhost:${PORT}`
); // eslint-disable-line no-console
});
登录页面:
服务器控制台:
这里是回购的 link 也有更多上下文:https://github.com/BenjDG/puzzle-gallery
感谢您提供的任何帮助!!!
- 当您发送不在 200 范围内的状态代码时,它在客户端代码中被视为“异常”。具体对于 Axios,执行
catch
块。在你的代码中,它是
.catch((err) => {
console.error(err);
});
所以您在控制台中收到了错误消息。
- 建议:可以使用status 200,最好在添加新用户前检查邮件是否已经在数据库中。
我认为错误 500 是为了防止您不知道该错误。在这种情况下,我们可以通过检查之前来处理重复错误。
如果您希望调用者优雅地处理错误,您可以考虑返回 200 响应,例如:
{
"success": true
}
或...
{
"success": false,
"errorCode": "UsernameAlreadyExists",
"message": "This username already exists."
}
调用者有责任检查 success
字段以确保请求成功。如果需要,您可以直接在您的应用程序中显示友好消息,或者您可以使用“错误代码”来确定要显示的内容。这对于 API 跨多个应用程序共享,并且您想要显示不同的消息,或者如果您支持多语言 UI,并且想要翻译消息。
很有帮助。
快说:
I know it is a bad idea to show all the server error messages to the user, but I would like to show a select few.
我相信您已经看到了对此发出警告的文章,所以稍微澄清一下。您不想将内部错误消息和堆栈跟踪传递给您的调用者,因为这暴露了比大多数客户应该知道的更多关于您系统的信息。攻击者可能会使用此信息来了解有关您的实施的更多信息,并使用它来利用您的系统。
一般来说,返回一条友好的错误消息或子状态代码(尤其是 4xx 错误)帮助调用者了解他们需要如何重新提交请求才能获得成功的响应并没有什么坏处.重要的是抽象出所有底层实现细节,所以不要只是将错误消息直接从 Mongoose 传递给调用者、捕获异常并发送适当的响应。
因为您正在处理身份验证 - 您还需要注意不要向调用者暴露太多信息。例如 - 公开一个“检查用户名”端点将使某人很容易暴力破解你的 API 在你的应用程序中获得少数有效用户。
我正致力于在 MongoDB MERN 应用程序中实现自定义错误处理。我也在使用 Mongoose 和 passport-local-mongoose。 当用户注册新帐户时,他们应该会在 chrome 控制台中收到一条特定的错误消息,内容为“用户名已存在”。我知道向用户显示所有服务器错误消息是个坏主意,但我想显示 select 几个。
我试过的链接: https://github.com/saintedlama/passport-local-mongoose
https://www.geeksforgeeks.org/nodejs-authentication-using-passportjs-and-passport-local-mongoose/
代码如下: server/controller/auth.js
const { User } = require('../models');
const register = async function (req, res) {
try {
const user = new User({ username: req.body.username });
await user.setPassword(req.body.password);
await user.save();
}
catch (err) {
console.log(`error inside save ${err}`);
res.status(500).send(err);
}
};
const login = async function (req, res) {
//code block under construction
console.log(`login!!!!!`);
};
const logout = function (req, res) {
req.session.destroy();
res.end();
};
exports.login = login;
exports.register = register;
exports.logout = logout;
server/models/User.js
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const passportLocalMongoose = require('passport-local-mongoose');
const userSchema = new Schema({
username: { type: String, unique: true },
password: { type: String}
});
userSchema.plugin(passportLocalMongoose);
const User = mongoose.model('User', userSchema);
module.exports = User;
server/routes/api/auth/index.js
const router = require('express').Router();
const passport = require('../../../config/passport');
const authController = require('../../../controllers/auth');
router.route('/logout').get(authController.logout);
router.route('/register').post(authController.register);
router.use(passport.authenticate('local', {
session: true
}));
// Matches with '/api/auth'
router.route('/login').post(authController.login);
module.exports = router;
server/server.js
const path = require('path');
const express = require('express');
const passport = require('./config/passport');
const mongoose = require('mongoose');
const cors = require('cors');
const session = require('express-session');
const helmet = require('helmet');
const morgan = require('morgan');
const corsOptions = require('./config/cors.js');
const routes = require('./routes');
const { v1: uuidv1 } = require('uuid');
// console.log(uuidv1());
const PORT = process.env.PORT || 3001;
const app = express();
mongoose.connect(process.env.MONGODB_URI || 'mongodb://localhost/puzzlegallery', {
useNewUrlParser: true,
useUnifiedTopology: true,
useCreateIndex: true,
useFindAndModify: false
});
mongoose.set("useCreateIndex", true);
// Define middleware here
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
app.use(helmet({ contentSecurityPolicy: false }));
app.use(session({ secret: 'sassy', resave: false, saveUninitialized: true }));
app.use(passport.initialize());
app.use(passport.session());
app.use(cors(corsOptions));
app.use(morgan('dev'));
app.use(routes);
// for Reactjs ##################
// Serve up static assets (usually on heroku)
if (process.env.NODE_ENV === 'production') {
app.use(express.static('client/build'));
}
// #################################################
if (process.env.NODE_ENV === 'production') {
app.get('*', (_, res) => {
res.sendFile(path.join(__dirname, '../client/build/index.html'));
});
}
app.listen(PORT, (err) => {
if (err) throw err;
console.log(
` Server is Ready and Listening on http://localhost:${PORT}`
); // eslint-disable-line no-console
});
登录页面:
服务器控制台:
这里是回购的 link 也有更多上下文:https://github.com/BenjDG/puzzle-gallery 感谢您提供的任何帮助!!!
- 当您发送不在 200 范围内的状态代码时,它在客户端代码中被视为“异常”。具体对于 Axios,执行
catch
块。在你的代码中,它是
.catch((err) => {
console.error(err);
});
所以您在控制台中收到了错误消息。
- 建议:可以使用status 200,最好在添加新用户前检查邮件是否已经在数据库中。
我认为错误 500 是为了防止您不知道该错误。在这种情况下,我们可以通过检查之前来处理重复错误。
如果您希望调用者优雅地处理错误,您可以考虑返回 200 响应,例如:
{
"success": true
}
或...
{
"success": false,
"errorCode": "UsernameAlreadyExists",
"message": "This username already exists."
}
调用者有责任检查 success
字段以确保请求成功。如果需要,您可以直接在您的应用程序中显示友好消息,或者您可以使用“错误代码”来确定要显示的内容。这对于 API 跨多个应用程序共享,并且您想要显示不同的消息,或者如果您支持多语言 UI,并且想要翻译消息。
快说:
I know it is a bad idea to show all the server error messages to the user, but I would like to show a select few.
我相信您已经看到了对此发出警告的文章,所以稍微澄清一下。您不想将内部错误消息和堆栈跟踪传递给您的调用者,因为这暴露了比大多数客户应该知道的更多关于您系统的信息。攻击者可能会使用此信息来了解有关您的实施的更多信息,并使用它来利用您的系统。
一般来说,返回一条友好的错误消息或子状态代码(尤其是 4xx 错误)帮助调用者了解他们需要如何重新提交请求才能获得成功的响应并没有什么坏处.重要的是抽象出所有底层实现细节,所以不要只是将错误消息直接从 Mongoose 传递给调用者、捕获异常并发送适当的响应。
因为您正在处理身份验证 - 您还需要注意不要向调用者暴露太多信息。例如 - 公开一个“检查用户名”端点将使某人很容易暴力破解你的 API 在你的应用程序中获得少数有效用户。