Express框架實現(xiàn)簡單攔截器功能示例
1、前言
在前文express框架+bootstrap美化ejs模板提到,考試成績屬于非公開的數(shù)據(jù)。需要根據(jù)瀏覽器端訪問的用戶的身份進(jìn)行判斷,如果是有權(quán)限的用戶才會返回相應(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, //強制保存 session 即使它并沒有變化,。默認(rèn)為 true。建議設(shè)置成 false
saveUninitialized: true,
cookie: {
// secure: true,
maxAge:2*60*60*1000 /*過期時間*/
},
rolling:true //在每次請求時重新設(shè)置 cookie,用于重置 cookie 過期時間(默認(rèn):false)
}))3.3、攔截器代碼編寫
因為app.js是站點訪問的入口文件,所以為了盡可能的攔截所有的web請求,攔截器需要寫在所有的app.use(準(zhǔn)確地說,是所有的路由)前。下面是從app.js中截取出來的代碼片斷:
//添加攔截器
app.use(function (req, res, next) {
if(req.session.user){
//已經(jīng)登錄過的用戶(存在session)
console.log("這個用戶已經(jīng)登陸:" + req.session.user.u_name);
next();
}else{
//用戶沒有登錄(session)前
var arr = req.url.split('/');
//去除get請求攜帶的參數(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 {
//最初請求的鏈接也做為參數(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上方,先引入一個路由文件,它可以為我們提供登錄的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};
//密碼校驗
//僅僅是個模板,省略了從數(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>同時,我在這里把score.ejs模板的代碼也貼出來(為本次演示功能的開發(fā)做了一些調(diào)整):
<!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、驗證
完成以上主要步驟之后,可以啟動網(wǎng)站試試了!
初次訪問一下http://localhost:3000/system,結(jié)果是下邊這樣的:
有沒有發(fā)現(xiàn),頁面重定向到了登錄頁面,此時鏈接也變成了localhost:3000/login/system,其實system是一個路由參數(shù)(用于告訴服務(wù)器,在登錄成功之后重定向的位置)。填寫賬號/密碼信息:李四/123456后,效果如下:
再進(jìn)一步驗證一下,把瀏覽器關(guān)閉,確保已經(jīng)與服務(wù)器斷開了鏈接,重新訪問主頁,按照login.js中的攔截規(guī)則,主頁/是不被攔截的。
果真如此。
4、寫在最后
整理到這里就結(jié)束了,雖然描述得不是很細(xì)致,但在以上章節(jié)的代碼中,我想信你可能能體會到攔截器的用途;并可以參照案例的代碼完成你的練習(xí)。
最近,在某項目實踐的過程中,發(fā)現(xiàn)lowdb這種非常輕便小巧的數(shù)據(jù)庫,我也成功地在express項目中完成了CRUD等基本功能。那一下節(jié),我就介紹一下這個數(shù)據(jù)庫,并講一講如何在express項目中使用lowdb數(shù)據(jù)庫完成基本的CRUD操作吧。
- node.js中koa和express的差異對比
- Node.js中Express框架使用axios同步請求(async+await)實現(xiàn)方法
- node.js使用express-jwt報錯:expressJWT?is?not?a?function解決
- Node.js使用express寫接口的具體代碼
- Node.js?express中的身份認(rèn)證的實現(xiàn)
- 使用Express+Node.js對mysql進(jìn)行增改查操作?
- node.js三個步驟實現(xiàn)一個服務(wù)器及Express包使用
- Node.js中Express框架的使用教程詳解
- node.js+express留言板功能實現(xiàn)示例
- node.js使用express-fileupload中間件實現(xiàn)文件上傳
- Node.js+express+socket實現(xiàn)在線實時多人聊天室
相關(guān)文章
初學(xué)者如何快速搭建Express開發(fā)系統(tǒng)步驟詳解
這篇文章主要介紹了初學(xué)者如何快速搭建Express開發(fā)系統(tǒng),結(jié)合實例形式詳細(xì)分析了express框架搭建的具體步驟與相關(guān)注意事項,需要的朋友可以參考下2023-05-05
node實現(xiàn)socket鏈接與GPRS進(jìn)行通信的方法
這篇文章主要介紹了node實現(xiàn)socket鏈接與GPRS進(jìn)行通信的方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-05-05
Node.js調(diào)用fs.renameSync報錯(Error: EXDEV, cross-device link not
這篇文章主要介紹了Node.js調(diào)用fs.renameSync報錯(Error: EXDEV, cross-device link not permitted),非常具有實用價值,需要的朋友可以參考下2017-12-12

