Express+Nodejs 下的登录拦截实现
Express+Nodejs 下的登录拦截实现
原来一直不知道怎么在Express+Nodejs里面添加类似于Struts2的拦截器(因为要使用登录拦截的功能)。 以前一直以为在router这块添加类似一下的转移路由控制权代码的(每个都加很麻烦)
app.get('/show', controllers.checkLogin);//登录验证
app.get('/show', controllers.showList);//实际跳转
又或者是像某些项目里面给每个controller的方法里面加以下这种验证(太繁琐了)
if (!req.session.user) {
return res.redirect("/login");
}
最近翻到之前使用session的代码片段,突然有如茅塞顿开啊!!
//session
app.use(function (req, res, next) {
var err = req.flash('error');
var success = req.flash('success');
res.locals({
user:req.session.user,
navSide:req.session.navSide,
error:err.length ? err : null,
success:success.length ? success : null
});
next();
});
这尼玛不就是个拦截器吗~囧~
稍加改造
//登录拦截器
app.use(function (req, res, next) {
var url = req.originalUrl;
if (url != "/login" && !req.session.user) {
return res.redirect("/login");
}
next();
});
经过测试,成功了
Express + Node.js 下的登录拦截实现
在Express + Node.js应用中,登录拦截是一个非常常见的需求。通过登录拦截,我们可以确保用户在访问受保护的页面前已经进行了身份验证。本文将介绍如何在Express应用中实现登录拦截。
原来的困惑
起初,我并不知道如何在Express应用中实现类似Struts2的拦截器功能。通常的做法是在每个路由处理函数前添加登录验证逻辑,例如:
app.get('/show', controllers.checkLogin); // 登录验证
app.get('/show', controllers.showList); // 实际跳转
或者在每个控制器方法内部添加登录验证逻辑,但这会显得非常繁琐:
if (!req.session.user) {
return res.redirect("/login");
}
发现解决方案
后来,我在项目的session中间件中找到了灵感。我发现session中间件实际上起到了类似拦截器的作用。于是,我决定稍微改造一下这段代码,使其成为一个登录拦截器。
登录拦截器实现
下面是具体的实现代码:
// 登录拦截器
app.use(function (req, res, next) {
// 获取请求的URL
var url = req.originalUrl;
// 如果当前访问的URL不是登录页面,并且用户未登录,则重定向到登录页面
if (url !== '/login' && !req.session.user) {
return res.redirect("/login");
}
// 如果满足条件,则继续执行下一个中间件或路由处理函数
next();
});
解释
-
获取请求的URL:
var url = req.originalUrl;
这行代码用于获取当前请求的URL路径。
-
判断是否需要进行登录验证:
if (url !== '/login' && !req.session.user) { return res.redirect("/login"); }
这里我们检查当前请求的URL是否为登录页面(
/login
),并且用户是否已经登录(即req.session.user
是否存在)。如果条件满足,我们将用户重定向到登录页面。 -
继续执行下一个中间件或路由处理函数:
next();
如果条件不满足,我们调用
next()
函数,让请求继续传递到下一个中间件或路由处理函数。
测试与验证
经过测试,上述代码能够成功地拦截未登录用户的访问,并将其重定向到登录页面。这样我们就实现了简单的登录拦截功能。
通过这种方式,我们避免了在每个路由处理函数前手动添加登录验证逻辑,使得代码更加简洁和易于维护。
希望这个示例对你有所帮助!
不错,我是用aop实现的
我用的是route的middleware实现的,你这个其实是实现了express的middleware,和session/bodyparser是一个级别的. 我的实现代码:
//set the authIdentity method for all the handlers.
//catch the exceptions for all the handlers.
var m = ['get','post','put','delete'];
m.forEach(function(type){
var handlers = app.routes[type];
if(handlers){
handlers.forEach(function(handler){
//TODO:need to config the excluded handler path,not the hard code.
if(handler.path !== '/' && handler.path !== '/auth'){//the '/auth' is the login url.
handler.callbacks = [authIdentity].concat(handler.callbacks);
}
handler.callbacks.forEach(function(callback){
var packageCallBack = function(req,res,next){
try{callback(req,res,next);}
catch(e){
debugger;
//TODO:need to implement other logics.
if(e instanceof AppError){
res.send(e);
}
next(e);
}
};
callback = packageCallBack;
});
});
}
});
静态资源app.use(express.static(path.join(__dirname, 'public')));
放在app.use(express.session());
后面登录拦截的前面,我的没问题
不懂struts, 但一般就middleware就好了。
var filter = require('./lib/filter');
判断是否已经登录如果登录了则过去,否则跳转到登录页
exports.authorize = function(req, res, next) {
if (!req.session.user_id) {
res.redirect('/admin/login');
} else {
next();
}
}
使用session
app.use(express.cookieParser('sctalk admin manager'));
app.use(express.session());
路由控制,在需要登录验证的路由上加上filter.authorize
app.get('/admin/login',admin.login);
app.get('/admin/logout',admin.logout);
app.get('/admin/:action',filter.authorize, function(req, res, next){
if(admin[req.params.action])
{
admin[req.params.action](req, res, next);
}
else
{
res.status(404);
res.end();
}
});
最后在登录判断时候添加session即可
exports.dologin = function(req, res,next){
// 校验
req.assert('username', "用户名不能为空").notEmpty();
req.assert('password', "密码不能为空").notEmpty();
var errors = req.validationErrors();
if(errors && errors.length>0)
{
var ermsg = [];
for(var i=0;i<errors.length;i++)
{
ermsg.push(errors[i].msg);
}
var json={title:'管理后台-- 请先登录',error:ermsg.join("\n")};
res.render('admin/login', json);
return;
}
var userid = req.body.username;
var pwd = req.body.password;
var ip = req.ip;
userbiz.checkUser(userid,pwd,ip,function(err,user){
if(!!err){
var json={title:'管理后台-- 请先登录',error:err};
res.render('admin/login', json);
}
else{
req.session.user_id = user.user_id;
req.session.user = user;
res.redirect("/admin/index");
}
});
};
倘若有N个路由都需要验证登录或者权限 那每个还都得添加一下filter 岂不是也很不方便
学习 正好想怎么弄登录呢
+1
楼主看下这个https://github.com/tldrio/express-group-handlers 我最近也在做这个东西,搜到了这个。
没登陆的时候 TypeError: Cannot read property ‘user_id’ of undefined 求解决
我是用Nodejs做server,前台和后台都用oauth2,通过access_token做登陆拦截
好东西~
这个确实不错。。。 aop了
思路大体差不多啊 实现有些前台地址不需要登陆的验证 login.js
var needLogin = function(path){
var noLoginPath = ['/','/ajax']; //不需要登陆的地址
for(var i =0; i< noLoginPath.length;i++)
{
var item = noLoginPath[i];
if(path == item || (item + '/') == path){
return false; //不需要登陆
}
}
return true;
}
module.exports = needLogin;
app.js
app.use(function(req,res,next){
var path = req.originalUrl;
var needLogin = require('./libs/login');
var err = null;
if(needLogin(path))
{
var login = req.session.islogin;
if(!login){
err = new Error('Not Login');
err.status = 500;
}
}
next(err);
})
也在弄这个,正好学习一下
楼主你好,我正在学习,能提供完整点的例子吗?
用装饰器吧。更直观好用。
在Express + Node.js 中实现登录拦截可以通过中间件来完成。中间件可以理解为一种处理请求的函数,在请求到达路由之前进行一些预处理或后处理。这里我们将创建一个中间件来检查用户是否已登录,并根据结果重定向。
示例代码
首先,确保你已经在项目中安装了Express:
npm install express
然后,在你的应用文件中设置中间件:
const express = require('express');
const session = require('express-session');
const app = express();
// 使用session中间件
app.use(session({
secret: 'your-secret-key',
resave: false,
saveUninitialized: true
}));
// 登录拦截中间件
function loginInterceptor(req, res, next) {
const url = req.originalUrl;
if (url !== '/login' && !req.session.user) {
return res.redirect('/login');
}
next();
}
// 应用登录拦截中间件
app.use(loginInterceptor);
// 示例登录路由
app.get('/login', (req, res) => {
// 模拟登录逻辑
req.session.user = { username: 'testUser' };
res.send('登录成功');
});
// 需要登录才能访问的路由
app.get('/protected', (req, res) => {
res.send('欢迎,' + req.session.user.username);
});
// 启动服务器
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
解释
-
Session 中间件:
express-session
是一个常用的库,用于管理会话状态。在这个例子中,我们使用它来存储用户登录状态。
-
登录拦截中间件:
loginInterceptor
函数检查当前请求的 URL 是否为/login
或者用户是否已登录 (req.session.user
)。- 如果用户未登录且尝试访问非登录页面,则重定向到登录页面。
-
路由:
- 我们定义了一个
/login
路由来模拟登录过程,并将用户信息存储在req.session
中。 - 定义了一个
/protected
路由,只有登录过的用户才能访问该路由。
- 我们定义了一个
通过这种方式,你可以轻松地在整个应用中实现统一的登录拦截机制,而无需在每个路由处理程序中重复相同的逻辑。