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();
});

经过测试,成功了


19 回复

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();
});

解释

  1. 获取请求的URL

    var url = req.originalUrl;
    

    这行代码用于获取当前请求的URL路径。

  2. 判断是否需要进行登录验证

    if (url !== '/login' && !req.session.user) {
        return res.redirect("/login");
    }
    

    这里我们检查当前请求的URL是否为登录页面(/login),并且用户是否已经登录(即req.session.user是否存在)。如果条件满足,我们将用户重定向到登录页面。

  3. 继续执行下一个中间件或路由处理函数

    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&lt; 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);
})

也在弄这个,正好学习一下

楼主你好,我正在学习,能提供完整点的例子吗?

用装饰器吧。更直观好用。

untitled1.png

在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');
});

解释

  1. Session 中间件

    • express-session 是一个常用的库,用于管理会话状态。在这个例子中,我们使用它来存储用户登录状态。
  2. 登录拦截中间件

    • loginInterceptor 函数检查当前请求的 URL 是否为 /login 或者用户是否已登录 (req.session.user)。
    • 如果用户未登录且尝试访问非登录页面,则重定向到登录页面。
  3. 路由

    • 我们定义了一个 /login 路由来模拟登录过程,并将用户信息存储在 req.session 中。
    • 定义了一个 /protected 路由,只有登录过的用户才能访问该路由。

通过这种方式,你可以轻松地在整个应用中实现统一的登录拦截机制,而无需在每个路由处理程序中重复相同的逻辑。

回到顶部