下面我将为你详细讲解“Nodejs进阶:express+session实现简易登录身份认证”的完整攻略。本攻略主要分为以下几个部分:
- 什么是session
- express-session的使用
- 实现简易登录身份认证的步骤
- 示例说明
什么是session
在Web开发中,我们常常需要通过用户的身份认证来实现一些特殊的操作。而在HTTP的无状态协议中,为了保存用户的认证状态,我们通常需要使用session来存储用户的登录信息。session是一种服务端技术,用于存储用户的会话信息,比如登录状态、购物车内容等。在用户访问网站时,服务端会生成一个session ID并将其返回给客户端,以便在后续的请求中识别出该用户的身份。
express-session的使用
在使用express-session之前,我们需要先安装并引入该模块:
npm install express-session --save
const session = require('express-session');
使用express-session非常简单,只需要在express中使用app.use(session(options))
即可。其中,options是一个可配置的选项对象,用于设置session的相关参数。常见的options参数如下:
- secret:用于配置加密session ID的秘钥,该秘钥不应该泄露给客户端,一般应该存储在服务端。例如:
app.use(session({ secret: 'keyboard cat' }));
- resave:当用户请求结束时,是否保存session的修改。如果设为true,则每次请求都会保存session的变化,不管需不需要。例如:
app.use(session({ resave: true }));
- saveUninitialized:当用户请求中未包含session ID时,是否创建新的session。如果设为true,则每次请求都会创建新的session。例如:
app.use(session({ saveUninitialized: true }));
- cookie:用于设置session的cookie选项,例如过期时间、路径、域名等。例如:
app.use(session({ cookie: { maxAge: 60000 }}));
- store:用于设置session的存储方式,常见的有Memory、Redis和MongoDB等。例如:
const MongoStore = require('connect-mongo')(session);
app.use(session({
secret: 'keyboard cat',
store: new MongoStore({ url: 'mongodb://localhost/test-app' })
}));
实现简易登录身份认证的步骤
实现简单的登录身份认证通常分为以下几个步骤:
-
准备用户登录表单,表单中需要包含用户名和密码两个输入框,并设置提交按钮的action为提交登录请求的路由。
-
编写登录请求路由,接收用户提交的用户名和密码,验证该用户是否合法,如果合法则使用express-session设置session信息,并重定向到用户首页;否则返回登录失败的提示信息。
-
用户访问其他页面时,使用express-session验证用户的身份是否已经通过认证,如果认证成功则显示该页面;否则重定向到用户登录页面。
下面我们通过一个完整的示例来演示上述步骤的实现:
const express = require('express');
const session = require('express-session');
const app = express();
// 设置session加密秘钥
app.use(session({ secret: 'keyboard cat' }));
// 用户登录页面
app.get('/', (req, res) => {
res.send(`
<h1>Login</h1>
<form method="POST" action="/login">
<input type="text" name="username" placeholder="Username" required><br>
<input type="password" name="password" placeholder="Password" required><br>
<button type="submit">Submit</button>
</form>
`);
});
// 处理用户登录请求
app.post('/login', (req, res) => {
const { username, password } = req.body;
// 模拟用户信息验证
if (username === 'admin' && password === '123456') {
// 设置session信息
req.session.user = { username };
// 重定向到用户页面
res.redirect('/home');
} else {
// 登录失败
res.send('Login failed');
}
});
// 用户首页
app.get('/home', (req, res) => {
// 验证session信息
if(req.session.user) {
res.send(`<h1>Welcome, ${req.session.user.username}</h1>`);
} else {
// 重定向到登录页面
res.redirect('/');
}
});
// 启动应用
app.listen(3000, () => {
console.log('App is running at http://localhost:3000');
});
在上述示例中,我们使用了express-session模块来设置session信息,包括用户登录和已登录状态的验证。表单的提交通过POST请求方式来处理,在处理该请求时,我们使用req.body来获取用户提交的登录信息,并进行了简单的合法性验证。如果验证通过,则设置session信息,然后重定向到用户首页。如果验证不通过,则返回登录失败的提示信息。在用户访问其他页面时,我们使用req.session来验证session信息是否存在,如果存在,则显示该页面的内容,否则重定向到用户登录页面。
示例说明
下面是两种使用express-session的示例场景:
示例1:购物车功能
在购物网站中,用户可以添加商品到购物车中,但是当用户关闭了网页后,购物车的内容会被清空。为了保存用户购物车的信息,我们可以使用session来存储购物车的内容,并在用户再次访问网站时恢复该购物车的内容。具体实现方法类似于示例中用户登录功能的处理方式。
const express = require('express');
const session = require('express-session');
const app = express();
// 设置session加密秘钥
app.use(session({ secret: 'keyboard cat' }));
// 商品列表页面
app.get('/products', (req, res) => {
res.send(`
<h1>Product List</h1>
<ul>
<li>Product A <a href="/add-to-cart?a=1">Add to cart</a></li>
<li>Product B <a href="/add-to-cart?a=2">Add to cart</a></li>
<li>Product C <a href="/add-to-cart?a=3">Add to cart</a></li>
</ul>
`);
});
// 加入购物车请求路由
app.get('/add-to-cart', (req, res) => {
const { a } = req.query;
// 判断购物车是否已经存在
if(req.session.cart) {
// 如果已经存在,则加入新的商品
req.session.cart.push(a);
} else {
// 如果不存在,则初始化购物车内容
req.session.cart = [a];
}
res.send('Success');
});
// 购物车页面
app.get('/cart', (req, res) => {
// 如果购物车存在,则显示购物车内容
if(req.session.cart) {
const products = ['Product A', 'Product B', 'Product C'];
const items = req.session.cart.map(a => `<li>${products[a-1]}</li>`);
res.send(`
<h1>My Shopping Cart</h1>
<ul>
${items.join('')}
</ul>
`);
} else {
res.send('<h1>Your shopping cart is empty</h1>');
}
});
// 启动应用
app.listen(3000, () => {
console.log('App is running at http://localhost:3000');
});
在上述示例中,我们使用session来存储购物车的内容,并在加入购物车和显示购物车的请求中读取session中的信息。在加入购物车时,我们先检查购物车是否已经存在,如果存在,则将新商品加入购物车,否则初始化购物车的内容。在显示购物车时,我们通过session中的购物车内容来生成商品列表,然后返回页面内容。
示例2:多用户在线聊天室
在在线聊天室中,我们需要使用session来识别不同的用户,并将发送的消息通知给所有的在线用户。具体实现方法类似于示例中用户登录功能的处理方式。
const express = require('express');
const session = require('express-session');
const app = express();
// 设置session加密秘钥
app.use(session({ secret: 'keyboard cat' }));
// 网页聊天室页面
app.get('/', (req, res) => {
res.send(`
<h1>Chat Room</h1>
<ul id="messages"></ul>
<input id="message" type="text">
<button onclick="send()">Send</button>
<script>
function send() {
const msg = document.getElementById('message').value;
const xhr = new XMLHttpRequest();
xhr.open('POST', '/message');
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send(JSON.stringify({ message: msg }));
}
const source = new EventSource('/stream');
source.onmessage = function(event) {
const el = document.createElement('li');
el.innerHTML = event.data;
document.getElementById('messages').appendChild(el);
};
</script>
`);
});
// 处理发送消息的请求
app.post('/message', (req, res) => {
// 判断用户是否已经登录
if(req.session.user) {
// 向所有在线用户发送消息
const msg = `${req.session.user.username}: ${req.body.message}`;
const clients = req.app.get('clients');
clients.forEach(client => client.send(msg));
res.send('Success');
} else {
res.send('Unauthorized');
}
});
// 处理用户登录请求
app.post('/login', (req, res) => {
const { username, password } = req.body;
// 模拟用户信息验证
if (username === 'admin' && password === '123456') {
// 设置session信息
req.session.user = { username };
// 重定向到网页聊天室页面
res.redirect('/');
} else {
// 登录失败
res.send('Login failed');
}
});
// 处理用户注销请求
app.get('/logout', (req, res) => {
// 清除session信息
req.session.destroy();
// 重定向到用户登录页面
res.redirect('/');
});
// 处理SSE请求
app.get('/stream', (req, res) => {
// 添加客户端到clients数组中
const clients = req.app.get('clients');
clients.push(res);
// 向客户端发送SSE消息
res.setHeader('Content-Type', 'text/event-stream');
res.setHeader('Cache-Control', 'no-cache');
res.setHeader('Connection', 'keep-alive');
res.write('\n');
req.on('close', () => {
// 从clients数组中移除客户端
clients.splice(clients.indexOf(res), 1);
});
});
// 启动应用
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });
wss.on('connection', (ws, req) => {
console.log('WebSocket connected');
// 将WebSocket连接保存到clients数组中
req.app.get('clients').push(ws);
ws.on('close', () => {
console.log('WebSocket disconnected');
// 从clients数组中移除WebSocket连接
const clients = req.app.get('clients');
clients.splice(clients.indexOf(ws), 1);
});
});
app.set('clients', []);
// 启动应用
app.listen(3000, () => {
console.log('App is running at http://localhost:3000');
});
在上述示例中,我们使用session来识别不同的用户,并在处理发送消息的请求时进行合法性验证。在接收到发送消息的请求,并验证用户身份合法后,我们向所有的在线用户发送消息。在页面中,我们通过SSE(Server-Sent Events)来实现实时消息的推送。在用户访问聊天室页面时,我们使用session来验证用户的身份是否已经通过认证,如果认证成功则显示该页面;否则重定向到用户登录页面。在客户端发送消息时,我们使用WebSocket将该消息发送到服务端,并向所有在线客户端广播该消息的内容。
至此,我们详细讲解了“Nodejs进阶:express+session实现简易登录身份认证”的完整攻略。希望能对你有所帮助。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Nodejs进阶:express+session实现简易登录身份认证 - Python技术站