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实现在线实时多人聊天室