Express框架實(shí)現(xiàn)簡單攔截器功能示例
1、前言
在前文express框架+bootstrap美化ejs模板提到,考試成績屬于非公開的數(shù)據(jù)。需要根據(jù)瀏覽器端訪問的用戶的身份進(jìn)行判斷,如果是有權(quán)限的用戶才會(huì)返回相應(yīng)的數(shù)據(jù)。這種功能就是本節(jié)我要說明的“攔截器”。
2、分析
首先,要完成攔截器的功能,需要有session的支持,我們需要下載express-session模塊:
npm install --save express-session
3、開發(fā)過程
3.1、引入express-session模塊
在入口腳本app.js中,引入express-session模塊:
var session = require("express-session");
3.2、完成session配置
在入口腳本app.js中,設(shè)置session到app上,完成session的配置:
// 設(shè)置session中間件 app.use(session({ secret: 'keyboard cat', resave: false, //強(qiáng)制保存 session 即使它并沒有變化,。默認(rèn)為 true。建議設(shè)置成 false saveUninitialized: true, cookie: { // secure: true, maxAge:2*60*60*1000 /*過期時(shí)間*/ }, rolling:true //在每次請(qǐng)求時(shí)重新設(shè)置 cookie,用于重置 cookie 過期時(shí)間(默認(rèn):false) }))
3.3、攔截器代碼編寫
因?yàn)閍pp.js是站點(diǎn)訪問的入口文件,所以為了盡可能的攔截所有的web請(qǐng)求,攔截器需要寫在所有的app.use(準(zhǔn)確地說,是所有的路由)前。下面是從app.js中截取出來的代碼片斷:
//添加攔截器 app.use(function (req, res, next) { if(req.session.user){ //已經(jīng)登錄過的用戶(存在session) console.log("這個(gè)用戶已經(jīng)登陸:" + req.session.user.u_name); next(); }else{ //用戶沒有登錄(session)前 var arr = req.url.split('/'); //去除get請(qǐng)求攜帶的參數(shù) for (var i = 0; i < arr.length; i++) { arr[i] = arr[i].split('?')[0]; } //羅列所有無需權(quán)限檢查的路由 if (arr[1] === 'login' || arr[1] === 'logout' || arr[1] === '') { next(); } else { //最初請(qǐng)求的鏈接也做為參數(shù)傳遞給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、登錄功能開發(fā)
在app.js上方,先引入一個(gè)路由文件,它可以為我們提供登錄的get和post請(qǐng)求處理;
var loginRouter = require('./routes/login');
在app.js文件中,將loginRouter綁定到/login這個(gè)路徑上:
像上邊這樣,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}; //密碼校驗(yàn) //僅僅是個(gè)模板,省略了從數(shù)據(jù)庫查詢的過程 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{ //認(rèn)證失敗 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>
同時(shí),我在這里把score.ejs模板的代碼也貼出來(為本次演示功能的開發(fā)做了一些調(diào)整):
<!DOCTYPE html> <html> <head> <title>成績單</title> <!-- 引入bootstrap樣式文件 注意這里的href是相對(duì)于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、驗(yàn)證
完成以上主要步驟之后,可以啟動(dòng)網(wǎng)站試試了!
初次訪問一下http://localhost:3000/system,結(jié)果是下邊這樣的:
有沒有發(fā)現(xiàn),頁面重定向到了登錄頁面,此時(shí)鏈接也變成了localhost:3000/login/system,其實(shí)system是一個(gè)路由參數(shù)(用于告訴服務(wù)器,在登錄成功之后重定向的位置)。填寫賬號(hào)/密碼信息:李四/123456后,效果如下:
再進(jìn)一步驗(yàn)證一下,把瀏覽器關(guān)閉,確保已經(jīng)與服務(wù)器斷開了鏈接,重新訪問主頁,按照login.js中的攔截規(guī)則,主頁/是不被攔截的。
果真如此。
4、寫在最后
整理到這里就結(jié)束了,雖然描述得不是很細(xì)致,但在以上章節(jié)的代碼中,我想信你可能能體會(huì)到攔截器的用途;并可以參照案例的代碼完成你的練習(xí)。
最近,在某項(xiàng)目實(shí)踐的過程中,發(fā)現(xiàn)lowdb這種非常輕便小巧的數(shù)據(jù)庫,我也成功地在express項(xiàng)目中完成了CRUD等基本功能。那一下節(jié),我就介紹一下這個(gè)數(shù)據(jù)庫,并講一講如何在express項(xiàng)目中使用lowdb數(shù)據(jù)庫完成基本的CRUD操作吧。
- node.js中koa和express的差異對(duì)比
- Node.js中Express框架使用axios同步請(qǐng)求(async+await)實(shí)現(xiàn)方法
- node.js使用express-jwt報(bào)錯(cuò):expressJWT?is?not?a?function解決
- Node.js使用express寫接口的具體代碼
- Node.js?express中的身份認(rèn)證的實(shí)現(xiàn)
- 使用Express+Node.js對(duì)mysql進(jìn)行增改查操作?
- node.js三個(gè)步驟實(shí)現(xiàn)一個(gè)服務(wù)器及Express包使用
- Node.js中Express框架的使用教程詳解
- node.js+express留言板功能實(shí)現(xiàn)示例
- node.js使用express-fileupload中間件實(shí)現(xiàn)文件上傳
- Node.js+express+socket實(shí)現(xiàn)在線實(shí)時(shí)多人聊天室
相關(guān)文章
Node.js中path.resolve與path.join的區(qū)別與作用詳解
path.resolve和path.join都是屬于path核心模塊下的方法,用來拼接路徑,下面這篇文章主要給大家介紹了關(guān)于Node.js中path.resolve與path.join的區(qū)別與作用的相關(guān)資料,需要的朋友可以參考下2023-03-03nodejs 實(shí)現(xiàn)模擬form表單上傳文件
使用nodejs來模擬form表單進(jìn)行文件上傳,可以同時(shí)上傳多個(gè)文件。2014-07-07搭建一個(gè)Koa后端項(xiàng)目腳手架的方法步驟
這篇文章主要介紹了搭建一個(gè)Koa后端項(xiàng)目腳手架的方法步驟,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-05-05為nuxt項(xiàng)目寫一個(gè)面包屑cli工具實(shí)現(xiàn)自動(dòng)生成頁面與面包屑配置
這篇文章主要介紹了為nuxt項(xiàng)目寫一個(gè)面包屑cli工具實(shí)現(xiàn)自動(dòng)生成頁面與面包屑配置,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09Node.js中的HTTP?Server對(duì)象與GET、POST請(qǐng)求
這篇文章介紹了Node.js中的HTTP?Server對(duì)象與GET、POST請(qǐng)求,文中通過示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-07-07