一、什么是session
session,即会话,在Node.js中属于Web应用的内部机制,它记录了用户在应用程序中的会话状态。服务器在给客户端返回响应时,会随之返回一个sessionID,该ID会在客户端被记录下来。客户端之后每次访问服务器时,都会携带着这个sessionID一同发送给服务器,以识别当前访问者的身份。
二、Nodejs中session的简单使用
- 安装express-session
使用express-session中间件实现session机制需要先安装express-session模块,用npm命令直接安装即可
npm install express-session
- 在app.js中使用express-session中间件
在需要使用session的应用程序中引入express-session中间件
const session = require('express-session');
const app = express();
确保该中间件在路由中间件之前加载,并将其挂载到app对象上
app.use(session({
secret: 'mysession', // session的签名(加密)字符串,用于防止篡改cookie
resave: false, // 每次请求是否重新生成sessionID
saveUninitialized: true, // 保存未初始化的session
cookie: { maxAge: 1000 * 60 * 60 * 24 } // session会话物理存储时间
}));
以上配置了一些session中间件的初始化参数,如签名字符串secret用于防止篡改cookie,resave设置为false表示每次请求是否重新生成sessionID,saveUninitialized设置为true表示保存未初始化的session,cookie对象配置表示session会话物理存储时间为一天
- 使用session
使用req.session
访问session,具体实验见下
app.get('/session-test', (req, res) => {
if (req.session.isVisit) {
req.session.isVisit++;
res.send(`<p>第${req.session.isVisit}次来此页面</p>`);
} else {
req.session.isVisit = 1;
res.send('欢迎第一次来此页面');
}
});
以上代码编写了一个简单的路由,请求该路由时如果是第一次来访问,就缓存一个isVisit值为1,表示第一次访问。若是第二次及以上的访问,就做求HTTP请求并将之前的isVisit值+1,表示是第几次访问。
- 销毁session
使用req.session.destory()
方法可以立即注销掉该用户的session
app.get('/session-destroy', (req, res) => {
req.session.destroy((err) => {
if (err) {
console.log(err);
} else {
console.log(`session destroyed`);
res.send(`session destroyed`);
}
});
});
以上代码实现了一个路由,请求该路由时可以立即销毁用户的session,并在后端记录一条“session destroyed”的日志
三、利用session实现身份验证
session机制是构建Web应用的一项重要的内部机制,它为构建身份验证所需的数据扮演着重要角色。利用session进行身份验证,主要包括以下步骤:
- 登录
当用户输入合法的登录信息,服务器端会验证用户身份,并如果成功登录,则在session中缓存用户登录状态。
app.post('/login', (req, res) => {
const { username, password } = req.body;
if (username && password) {
// 检验没有问题,修改session中isLogin状态
req.session.isLogin = true;
req.session.username = username;
res.redirect('/');
} else {
res.redirect('/login');
}
})
- 访问受限资源
在需要进行身份验证的路由中,首先需要加入身份验证中间件,对用户是否合法进行验证。代码实现如下:
const auth = (req, res, next) => {
if(req.session.isLogin) {
next();
}else {
res.redirect('/login');
}
}
- 登出
登出操作其实就是删除session中缓存的登录状态。代码如下:
app.get('/logout', (req, res) => {
req.session.destroy((err) => {
if(err) throw err;
})
res.redirect('/');
})
四、示例
- 简单的登录验证
这个示例是一个临时存放的登录验证页面,它的主要功能是验证用户名和密码是否正确,正确后才能进入受限制的页面。代码如下
const express = require('express');
const bodyParser = require('body-parser');
const session = require('express-session');
const app = express();
app.use(bodyParser.urlencoded({extended: true}));
// 使用session中间件
app.use(session({
secret: 'mysession',
resave: false,
saveUninitialized: true,
cookie: { maxAge: 1000*60*60*24 } // session会话使用的时间
}));
// 页面路由
app.get('/login', (req, res) => {
res.send(`
<h1>登录页面</h1>
<form method='post' action='/login'>
<p><input name='username' placeholder='用户名'></p>
<p><input name='password' placeholder='密码'></p>
<p><button type='submit'>登录</button></p>
</form>
`)
})
app.post('/login', (req, res) => {
const {username, password} = req.body;
if (username && password) {
if (username === 'admin' && password === '123456') {
req.session.isLogin = true;
res.redirect('/');
} else {
res.send(`用户名或密码错误`);
}
} else {
res.send(`用户名或密码不能为空`);
}
})
app.get('/', (req, res) => {
if (req.session.isLogin) {
res.send(`
<h1>欢迎来到首页</h1>
<a href='/restricted-view'>进入受限制的页面</a>
<a href='/logout'>退出登录</a>
`);
} else {
res.send(`
<h1>您尚未登录</h1>
<a href='/login'>进入登录页面</a>
`);
}
})
const auth = (req, res, next) => {
if(req.session.isLogin) {
next();
}else {
res.redirect('/login');
}
}
app.get('/restricted-view', auth, (req, res) => {
res.send(`
<h2>您已登录,可以允许查看此页面</h2>
<a href='/'>返回首页</a>
`);
})
app.get('/logout', (req, res) => {
req.session.destroy((err) => {
if(err) throw err;
})
res.redirect('/');
})
app.listen(3000, (err) => {
if (err) throw err;
console.log(`server is listening on port 3000`);
})
- 在Express+MongoDB中使用session进行身份验证
这个示例是一个使用Express+MongoDB来创建的Node.js应用,它使用session机制来进行身份验证。代码实现如下:
/* Dependencies loading*/
const express = require('express');
const bodyParser = require('body-parser');
const session = require('express-session');
const mongoose = require('mongoose');
/* Configuring server and database */
const app = express();
mongoose.Promise = global.Promise;
mongoose.connect('mongodb://localhost/db_name', {useNewUrlParser: true, useUnifiedTopology: true}).then(() => {
console.log('connection to database successful');
}).catch((err) => {
console.log(`error occurred with message ${err}`);
})
/* Adding middlewares */
app.use(bodyParser.urlencoded({extended: true}));
app.use(session({secret: 'mysession', resave: false, saveUninitialized: true, cookie: { maxAge: 1000*60*60*24 }}));
app.use(express.static(__dirname + '/public/'));
/* Defining Models */
const User = mongoose.model('User', {
username: {
type: String,
required: true,
trim: true,
unique: true
},
password: {
type: String,
required: true,
trim: true
}
});
/* Routers*/
app.post('/login', (req, res) => {
const {username, password} = req.body;
if (username && password) {
User.findOne({username, password}).exec((err, user) => {
if (err) {
res.send(`login error with message ${err}`);
} else if (user) {
req.session.isLogin = true;
req.session.username = username;
req.session.userId = user._id.toString();
res.redirect('/restricted-view');
} else {
res.send(`username or password incorrect`);
}
})
} else {
res.send(`username or password can not be empty`);
}
})
const auth = (req, res, next) => {
if(req.session.isLogin) {
next();
}else {
res.redirect('/login');
}
}
app.get('/restricted-view', auth, (req, res) => {
res.sendFile(path.join(__dirname, './public/restricted-view.html'));
})
app.get('/', (req, res) => {
if(req.session.isLogin) {
res.sendFile(path.join(__dirname, './public/index-logged-in.html'));
} else {
res.sendFile(path.join(__dirname, './public/index-not-logged-in.html'));
}
})
/* starting app */
app.listen(3000, (err) => {
if (err) throw err;
console.log(`server is listening on port 3000`);
})
以上示例中,在/login路由处,如果输入的用户名和密码都正确,则会在session中缓存用户的登录状态、用户名和用户ID。在受限制的视图页中,如果用户访问当前页面以前并没有登录(即session中没有记录用户登录状态),就会被重定向到登录页面,被告知需要登录才能访问受限制视图。如果用户已经登录过,就会加载视图并在视图中显示出用户ID、用户名等内容。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Nodejs中session的简单使用及通过session实现身份验证的方法 - Python技术站