本篇内容主要讲解“Node怎么运用Cookie和Session进行登录验证”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Node怎么运用Cookie和Session进行登录验证”吧!
在凌海等地区,都构建了全面的区域性战略布局,加强发展的系统性、市场前瞻性、产品创新能力,以专注、极致的服务理念,为客户提供网站建设、成都做网站 网站设计制作按需策划,公司网站建设,企业网站建设,品牌网站制作,成都营销网站建设,外贸营销网站建设,凌海网站建设费用合理。
在vies
目录下新建login.ejs
:
登录页面
注意:页面中请求的接口是
POST /api/login
请求
在routes
目录下新建login.js
,该文件定义login
页面的页面路由:
var express = require("express");
var router = express.Router();
/* GET login page. */
router.get("/", function (req, res, next) {
res.render("login");
});
module.exports = router;
在app.js
中挂载页面路由:
// 引入
var loginRouter = require("./routes/login");
// 挂载
app.use("/login", loginRouter);
启动项目,访问http://localhost:3000/login
正常显示:
在services/UserService.js
中定义接口的模型(M层):
const UserService = {
// .......
// 登录查询
login: (username, password) => {
// 向数据库查询该用户
return UserModel.findOne({ username, password });
},
};
在controllers/UserController.js
中定义接口的控制层(C层):
const UserController = {
// ......
// 登录验证
login: async (req, res, next) => {
try {
const { username, password } = req.body;
const data = await UserService.login(username, password);
// console.log(data);
if (data) {
res.send({ ok: 1, msg: "登录成功!", data });
} else {
res.send({ ok: 0, msg: "用户不存在,登录失败!" });
}
} catch (error) {
console.log(error);
}
},
};
在routes/users.js
中定义Api
路由:
// 登录校验
router.post("/login", UserController.login);
至此登录页面就搭建好了:
在上一节Cookie-Session
登录验证工作原理的介绍中我们知道:
这个过程显然是比较复杂的,在express
中有一个express-session
模块可以大大降低我们的工作量,让我们站在巨人的肩膀上开发!
下载express-session
:
npm i express-session
在app.js
中进行配置:
// 引入express-session
var session = require("express-session");
// 配置session:需要放在在路由配置的前面
app.use(
session({
name: "AilixUserSystem", // cookie名字
secret: "iahsiuhaishia666sasas", // 密钥:服务器生成的session的签名
cookie: {
maxAge: 1000 * 60 * 60, // 过期时间:一个小时过期
secure: false, // 为true时表示只有https协议才能访问cookie
},
resave: true, // 重新设置session后会重新计算过期时间
rolling: true, // 为true时表示:在超时前刷新时cookie会重新计时;为false表示:在超时前无论刷新多少次,都是按照第一次刷新开始计时
saveUninitialized: true, // 为true时表示一开始访问网站就生成cookie,不过生成的这个cookie是无效的,相当于是没有激活的信用卡
})
);
配置好后,就会发现浏览器中有一个名为AilixUserSystem
的cookie
:
这是因为express-session
会自动解析cookie
和向前端设置cookie
,相当于是图一中的3、6(前半部分:通过SessionId
查询到Session
),我们不再需要手动对cookie
进行操作。
在登录成功时设置session
:
// controllers/UserController.js
// ....
// 登录校验
login: async (req, res, next) => {
try {
const { username, password } = req.body;
const data = await UserService.login(username, password);
// console.log(data);
if (data) {
// 设置session:向session对象内添加一个user字段表示当前登录用户
req.session.user = data; // 默认存在内存中,服务器一重启就没了
res.send({ ok: 1, msg: "登录成功!", data });
} else {
res.send({ ok: 0, msg: "用户不存在,登录失败!" });
}
} catch (error) {
console.log(error);
}
},
我们向req.session
中添加了一个user
字段,来保存用户登录的信息,这一步相当于是 图一中的1(SessionId会由express-session
模块自动生成)、2。
req.session
是一个session
对象,需要注意的是这个对象虽然存在于req
中,但其实不同的人访问系统时他们的req.session
是不同的,因为req.session
是根据我们设置的cookie
(由express-session
模块自动生成的AilixUserSystem
)生成的,每一个人访问系统所生成的cookie
是独一无二的,所以他们的req.session
也是独一无二的。
在收到请求时校验session
,在app.js
添加以下代码:
// 设置中间件:session过期校验
app.use((req, res, next) => {
// 排除login相关的路由和接口
// 这个项目中有两个,一个是/login的页面路由,一个是/api/login的post api路由,这两个路由不能被拦截
if (req.url.includes("login")) {
next();
return;
}
if (req.session.user) {
// session对象内存在user,代表已登录,则放行
// 重新设置一下session,从而使session的过期时间重新计算(在session配置中配置了: resave: true)
// 假如设置的过期时间为1小时,则当我12点调用接口时,session会在1点过期,当我12点半再次调用接口时,session会变成在1点半才会过期
// 如果不重新计算session的过期时间,session则会固定的1小时过期一次,无论这期间你是否进行调用接口等操作
// 重新计算session的过期时间的目的就是为了防止用户正在操作时session过期导致操作中断
req.session.myData = Date.now();
// 放行
next();
} else {
// session对象内不存在user,代表未登录
// 如果当前路由是页面路由,,则重定向到登录页
// 如果当前理由是api接口路由,则返回错误码(因为针对ajax请求的前后端分离的应用请求,后端的重定向不会起作用,需要返回错误码通知前端,让前端自己进行重定向)
req.url.includes("api")
? res.status(401).send({ msg: "登录过期!", code: 401 })
: res.redirect("/login");
}
});
注意:这段代码需要在路由配置的前面。
这段代码中我们通过req.session.myData = Date.now();
来修改session
对象,从而触发session
过期时间的更新(session
上myData
这个属性以及它的值 Date.now()
只是我们修改session
对象的工具,其本身是没有任何意义的),你也可以使用其它方法,只要能将req.session
修改即可。
因为我们这个项目是后端渲染模板的项目,并不是前后端分离的项目,所以在配置中间件进行session
过期校验拦截路由时需要区分Api路由
和页面路由
。
后端在拦截API路由后,向前端返回错误和状态码:
这个时候需要让前端自己对返回结果进行判断从而进行下一步的操作(如回到登录页或显示弹窗提示),该系统中前端是使用JavaScript
内置的fetch
来进行请求发送的,通过它来对每一个请求结果进行判断比较麻烦,大家可以自行改用axios
,在axios
的响应拦截器中对返回结果做统一的判断。
向首页(index.ejs
)添加一个退出登录的按钮:
为按钮添加点击事件:
const exit = document.getElementById('exit')
// 退出登录
exit.onclick = () => {
fetch("/api/logout").then(res => res.json()).then(res => {
if (res.ok) {
location.href = "/login"
}
})
}
这里调用了GET /api/logout
接口,现在定义一下这个接口,在controllers/UserController.js
中定义接口的控制层(C层):
const UserController = {
// ......
// 退出登录
logout: async (req, res, next) => {
// destroy方法用来清除cookie,当清除成功后会执行接收的参数(一个后调函数)
req.session.destroy(() => {
res.send({ ok: 1, msg: "退出登录成功!" });
});
},
};
在routes/users.js
中定义Api
路由:
// 退出登录
router.get("/logout", UserController.logout);
前面我们通过 req.session.user = data;
设置的session默认是存放到内存中的,当后端服务重启时这些session
就会被清空,为了解决这一问题我们可以将session
存放到数据库中。
安装connect-mongo
:
npm i connect-mongo
connect-mongo是MongoDB会话存储,用于用
Typescript编写的连接
和Express
。
修改app.js
:
// 引入connect-mongo
var MongoStore = require("connect-mongo");
// 配置session
app.use(
session({
name: "AilixUserSystem", // cookie名字
secret: "iahsiuhaishia666sasas", // 密钥:服务器生成的session的签名
cookie: {
maxAge: 1000 * 60 * 60, // 过期时间:一个小时过期
secure: false, // 为true时表示只有https协议才能访问cookie
},
resave: true, // 重新设置session后会重新计算过期时间
rolling: true, // 为true时表示:在超时前刷新时cookie会重新计时;为false表示:在超时前无论刷新多少次,都是按照第一次刷新开始计时
saveUninitialized: true, // 为true时表示一开始访问网站就生成cookie,不过生成的这个cookie是无效的,相当于是没有激活的信用卡
store: MongoStore.create({
mongoUrl: "mongodb://127.0.0.1:27017/usersystem_session", // 表示新建一个usersystem_session数据库用来存放session
ttl: 1000 * 60 * 60, // 过期时间
}), // 存放数据库的配置
})
);
到此,相信大家对“Node怎么运用Cookie和Session进行登录验证”有了更深的了解,不妨来实际操作一番吧!这里是创新互联网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!