Express框架实现简单拦截器功能示例
作者:Teacher_Tian_2019
1、前言
在前文express框架+bootstrap美化ejs模板提到,考试成绩属于非公开的数据。需要根据浏览器端访问的用户的身份进行判断,如果是有权限的用户才会返回相应的数据。这种功能就是本节我要说明的“拦截器”。
2、分析
首先,要完成拦截器的功能,需要有session的支持,我们需要下载express-session模块:
npm install --save express-session
3、开发过程
3.1、引入express-session模块
在入口脚本app.js中,引入express-session模块:
var session = require("express-session");3.2、完成session配置
在入口脚本app.js中,设置session到app上,完成session的配置:
// 设置session中间件
app.use(session({
secret: 'keyboard cat',
resave: false, //强制保存 session 即使它并没有变化,。默认为 true。建议设置成 false
saveUninitialized: true,
cookie: {
// secure: true,
maxAge:2*60*60*1000 /*过期时间*/
},
rolling:true //在每次请求时重新设置 cookie,用于重置 cookie 过期时间(默认:false)
}))3.3、拦截器代码编写
因为app.js是站点访问的入口文件,所以为了尽可能的拦截所有的web请求,拦截器需要写在所有的app.use(准确地说,是所有的路由)前。下面是从app.js中截取出来的代码片断:
//添加拦截器
app.use(function (req, res, next) {
if(req.session.user){
//已经登录过的用户(存在session)
console.log("这个用户已经登陆:" + req.session.user.u_name);
next();
}else{
//用户没有登录(session)前
var arr = req.url.split('/');
//去除get请求携带的参数
for (var i = 0; i < arr.length; i++) {
arr[i] = arr[i].split('?')[0];
}
//罗列所有无需权限检查的路由
if (arr[1] === 'login' || arr[1] === 'logout' || arr[1] === '') {
next();
} else {
//最初请求的链接也做为参数传递给login页面
res.redirect('/login' + req.url); // 将用户重定向到登录页面
res.end();
}
}
});
/* 尽可能让拦截器在所有路由的前边 */
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.use('/', indexRouter);
/* 略 */3.4、登录功能开发
在app.js上方,先引入一个路由文件,它可以为我们提供登录的get和post请求处理;
var loginRouter = require('./routes/login'); 在app.js文件中,将loginRouter绑定到/login这个路径上:
像上边这样,app.js的改造就完成了。接下来看一看./routes/login.js的代码吧:
var express = require('express');
var router = express.Router();
/* GET login */
router.get('/', function(req, res, next) {
if(req.session.user){
res.redirect("/"); // 将用户重定向到登录页面
res.end();
}else{
res.render('login', {redirect_path:""});
}
});
router.get('/:redirect_path', function(req, res, next) {
var redirect_path = req.params.redirect_path || "/";
if(req.session.user){
res.redirect("/" + redirect_path); // 将用户重定向到登录页面
res.end();
}else{
res.render('login', {redirect_path});
}
});
/* POST login */
router.post('/', function(req, res, next) {
var {u_name,u_password,redirect_path} = req.body;
var user = {u_name,u_password};
//密码校验
//仅仅是个模板,省略了从数据库查询的过程
if((u_name == "张三" || u_name == "李四") && u_password == "123456"){
//写入session
// req.session.user = {u_name,u_password};
req.session.regenerate(() => {
req.session.user = user;
req.session.success = "Authenticated as " + user.u_name;
res.redirect("/" + redirect_path); // 将用户重定向到登录页面
res.end();
});
}else{
//认证失败
res.redirect('/login' + req.url); // 将用户重定向到登录页面
res.end();
}
});
module.exports = router;在./routes/login.js中提及了login.ejs模板,代码如下:
<!DOCTYPE html>
<html>
<head>
<title>Login</title>
<link rel='stylesheet' href='/stylesheets/style.css' />
</head>
<body>
<form action="/login" method="POST">
<div>
<input type="hidden" name="redirect_path" value = "<%=redirect_path%>">
</div>
<div>
用户名:<input type="text" name="u_name" />
</div>
<div>
密码:<input type="password" name="u_password" />
</div>
<div>
<input type="submit" value="登录">
</div>
</form>
</body>
</html>同时,我在这里把score.ejs模板的代码也贴出来(为本次演示功能的开发做了一些调整):
<!DOCTYPE html>
<html>
<head>
<title>成绩单</title>
<!-- 引入bootstrap样式文件 注意这里的href是相对于public目录的 -->
<link rel="stylesheet" href="/stylesheets/bootstrap.min.css" rel="external nofollow" >
<link rel='stylesheet' href='/stylesheets/style.css' />
</head>
<body>
<div><%= year %>年高考成绩查询(<%= u_name%>)</div>
<table>
<% scores.forEach(function(item,index){ %>
<tr><td><%= index + 1 %></td><td><%=item.course %></td><td><%=item.score %></td></tr>
<% }); %>
</table>
</body>
</html>4、验证
完成以上主要步骤之后,可以启动网站试试了!
初次访问一下http://localhost:3000/system,结果是下边这样的:
有没有发现,页面重定向到了登录页面,此时链接也变成了localhost:3000/login/system,其实system是一个路由参数(用于告诉服务器,在登录成功之后重定向的位置)。填写账号/密码信息:李四/123456后,效果如下:
再进一步验证一下,把浏览器关闭,确保已经与服务器断开了链接,重新访问主页,按照login.js中的拦截规则,主页/是不被拦截的。
果真如此。
4、写在最后
整理到这里就结束了,虽然描述得不是很细致,但在以上章节的代码中,我想信你可能能体会到拦截器的用途;并可以参照案例的代码完成你的练习。
最近,在某项目实践的过程中,发现lowdb这种非常轻便小巧的数据库,我也成功地在express项目中完成了CRUD等基本功能。那一下节,我就介绍一下这个数据库,并讲一讲如何在express项目中使用lowdb数据库完成基本的CRUD操作吧。
您可能感兴趣的文章:
- node.js中koa和express的差异对比
- Node.js中Express框架使用axios同步请求(async+await)实现方法
- node.js使用express-jwt报错:expressJWT is not a function解决
- Node.js使用express写接口的具体代码
- Node.js express中的身份认证的实现
- 使用Express+Node.js对mysql进行增改查操作
- node.js三个步骤实现一个服务器及Express包使用
- Node.js中Express框架的使用教程详解
- node.js+express留言板功能实现示例
- node.js使用express-fileupload中间件实现文件上传
- Node.js+express+socket实现在线实时多人聊天室
