前言
Express 是一个简洁而强大的 Node.js Web 应用框架,它提供了丰富的中间件来帮助开发者快速构建 Web 应用。
前面我写的express专栏中很少涉及express中间件的用法,因此现在补充一些常用的中间件。
本篇文章我们将深入探讨 Express 的两个重要知识点:express-session、express-validator,并展示如何将它们有效地结合起来,以构建一个功能更强大、更安全的 Express 应用。
准备工作
创建和初始化express项目(创建和初始化操作可以看专栏文章)

一、express-session:会话管理
express-session是一个用于管理会话的中间件,它允许你在不同的请求之间存储和访问用户的会话数据。在用户登录、购物车管理等场景中非常有用。
安装
npm install express-session
代码示例
在 app.js 中添加以下代码:
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
const session = require('express-session');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
// 配置 session
app.use(session({
secret: 'kainama',
resave: false,
saveUninitialized: true,
cookie: { secure: false } // 在生产环境中,建议设置为 true
}));
// 示例路由,设置和获取会话数据
app.get('/set-session', (req, res) => {
req.session.username = 'JohnDoe';
res.send('Session set successfully');
});
app.get('/get-session', (req, res) => {
const username = req.session.username;
if (username) {
res.send(`Welcome, ${username}`);
} else {
res.send('No session data found');
}
});
app.use('/', indexRouter);
app.use('/users', usersRouter);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
module.exports = app;
测试
使用api测试工具,发送get请求 (设置会话数据)

发送get请求(获取会话数据)

在上述代码中,我们首先引入了
express-session并进行了配置。然后创建了两个路由,一个用于设置会话数据,另一个用于获取会话数据。PS:一定要注意发送顺序,比如你后发送设置会话数据,而先进行获取会话数据,那么肯定是获取不到username的值。
二、express-validator:输入验证
express-validator是一个用于验证和清理用户输入的中间件,它可以帮助你防止恶意输入和数据损坏。
安装
npm install express-validator
代码示例
在 app.js 中添加以下代码:
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
const { check, validationResult } = require('express-validator');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
// 示例路由,验证用户输入
app.post('/validate', [
check('email').isEmail().withMessage('Invalid email'),
check('password').isLength({ min: 6 }).withMessage('Password must be at least 6 characters')
], (req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
res.send('Input validated successfully');
});
app.use('/', indexRouter);
app.use('/users', usersRouter);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
module.exports = app;
比如这里我们设置是对email和password进行了数据验证
- email:需要满足邮箱格式
- password:不小于6位
代码语句分析
check('email').isEmail().withMessage('Invalid email')
1.
check('email')
check是express-validator库提供的一个函数,它的作用是指定要验证的字段。'email'是要验证的字段名,通常是表单中的一个输入字段名或者请求体中的一个属性名。在处理 HTTP 请求时,check函数会从请求体、查询字符串、URL 参数等位置查找名为2.
.isEmail()
- 这是一个验证器方法,它是
check函数返回的验证对象的一个方法。isEmail()用于验证user@example.com是有效的,而userexample.com是无效的。3.
.withMessage('Invalid email')
withMessage方法用于为验证失败的情况提供自定义的错误消息。- 当
isEmail()验证失败时,会生成一个包含错误信息的对象,这个错误信息就是'Invalid email'。在后续处理验证结果时,可以使用这个错误信息来给用户反馈具体的错误原因。
测试
错误的email格式

返回的结果

错误的密码格式

返回的结果

email和密码均不符合验证


正确的验证格式

三、结合使用的案例
创建一个简单的用户登录系统。在这个系统中,用户需要输入有效的电子邮件和密码进行登录,登录成功后会将用户信息存储在会话中,后续可以通过会话检查用户是否已登录。
代码示范
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
const session = require('express-session');
const { check, validationResult } = require('express-validator');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(logger('dev'));
app.use(express.json());
// app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
// 配置 session
app.use(session({
secret: 'kainama',
resave: false,
saveUninitialized: true,
cookie: { secure: false } // 在生产环境中,建议设置为 true
}));
// 解析表单数据
app.use(express.urlencoded({ extended: true }));
// 模拟用户数据库
const users = [
{ email: 'test@qq.com', password: 'root123' }
];
// 登录页面
app.get('/login', (req, res) => {
res.send(`
<form method="post" action="/login">
<label for="email">Email:</label>
<input type="email" id="email" name="email" required><br>
<label for="password">Password:</label>
<input type="password" id="password" name="password" required><br>
<button type="submit">Login</button>
</form>
`);
});
// 处理登录请求
app.post('/login', [
// 验证电子邮件
check('email')
.isEmail()
.withMessage('Please enter a valid email address'),
// 验证密码长度
check('password')
.isLength({ min: 6 })
.withMessage('Password must be at least 6 characters long')
], (req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
const { email, password } = req.body;
const user = users.find(u => u.email === email && u.password === password);
if (user) {
// 登录成功,将用户信息存储在会话中
req.session.user = user;
res.send('Login successful!');
} else {
res.status(401).send('Invalid email or password');
}
});
// 受保护的路由,需要登录才能访问
app.get('/dashboard', (req, res) => {
const user = req.session.user;
if (user) {
res.send(`Welcome to the dashboard, ${user.email}!`);
} else {
res.status(401).send('Please log in to access this page');
}
});
// 注销路由
app.get('/logout', (req, res) => {
req.session.destroy((err) => {
if (err) {
console.error(err);
}
res.send('Logged out successfully');
});
});
app.use('/', indexRouter);
app.use('/users', usersRouter);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
module.exports = app;
启动服务,访问http://localhost:3000/login

测试
使用测试的账号密码



访问受保护的路由


大家可以自行测试登录失败、未登录前访问受保护路由的情况。
四、小结
通过结合使用
express-session、express-validator,我们可以构建一个功能更强大、更安全的 Express 应用。express-session帮助我们管理用户会话,express-validator确保用户输入的有效性。这些中间件的组合可以大大提高开发效率和应用的安全性。

Express中间件实战:会话与输入验证

被折叠的 条评论
为什么被折叠?



