原来一直不知道怎么在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();
});
经过测试,成功了
不错,我是用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;
});
});
}
});
@duyinghua 我使用你这个方式在用登录拦截的时候,我放在了。app.use(express.session()); app.use(app.router);
之间,这样拦截是成功了,。但是静态的资源不能读取了。
不懂struts, 但一般就middleware就好了。
@duyinghua 感谢你的回复,拦截是成功了,但是新的问题出现了,session的写入始终是失败的, 我的文件配置app.js如下
`app.configure(function(){ app.set(‘port’, process.env.PORT || 3000); app.set(‘views’, __dirname + ‘/views’); app.set(‘view engine’, ‘ejs’); //app.use(express.logger()); app.use(express.static(path.join(__dirname, ‘public’))); app.use(express.favicon()); app.use(express.logger(‘dev’)); app.use(express.bodyParser()); app.use(express.methodOverride()); app.use(express.cookieParser(“keyboard cat”)); app.use(express.session()); app.use(function(req,res,next){ var url = req.originalUrl; if(url != “/login” && !req.session.user){ return res.redirect("/login"); // return; } next(); }) app.use(app.router);
}); ` session的写入是在另外一个route里面,具体实现方式是:
`exports.to_login = function(req, res){ var user_name = req.body.user_name; var password = req.body.password; console.log(user_name); console.log(password); var user = { username:user_name, password:password } req.session.user = user; res.render(“index”,{user:req.session.user}); }
`
这样之后,每次点击登陆之后都会又被拦截到登陆页面
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");
}
});
};
@duyinghua 你可以表达式 一个设置满足多个路由规则的呀。
@duyinghua ‘/admin/:action’ 是个通配符看到哇?
学习 正好想怎么弄登录呢
@duyinghua 不是啊,自己写的
+1
楼主看下这个https://github.com/tldrio/express-group-handlers 我最近也在做这个东西,搜到了这个。
@ronin session不能写入解决了吗,我也遇到了
没登陆的时候 TypeError: Cannot read property ‘user_id’ of undefined 求解决
我是用Nodejs做server,前台和后台都用oauth2,通过access_token做登陆拦截
@mypayne session 没有启用吗?
好东西~
这个确实不错。。。 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);
})
也在弄这个,正好学习一下
@xuanye 你好, require(’./lib/filter’);这个是什么模块?
楼主你好,我正在学习,能提供完整点的例子吗?