麻烦authentication

在使用护照本地策略执行我的restful apiauthentication时,我正面临一个混淆问题。

注意:当我在index.js中完成所有工作时,我的authentication工作已经成功。 但我想在类中使用更好的代码分离。

我有一个passport.js模块

// config/passport.js // load all the things we need var LocalStrategy = require('passport-local').Strategy; // load up the user model var mysql = require('mysql'); var dbconfig = require('./database'); var connection = mysql.createConnection(dbconfig.connection); module.exports = function(passport) { // passport needs ability to serialize and unserialize users out of session passport.serializeUser(function (user, done) { //console.log("SER"); console.log(user), done(null, user); }); passport.deserializeUser(function (user, done) { console.log("XXXX"); console.log(user); connection.query("SELECT * FROM users WHERE name = ? ",user.name, function(err, rows){ console.log("DER"); console.log(rows); done(err, rows[0]); }); }); // passport local strategy for local-login, local refers to this app passport.use('local-login', new LocalStrategy( function (username, password, done) { console.log("hhh"); console.log(username); connection.query("SELECT * FROM users WHERE name = ? ",username, function(err, rows){ console.log(rows); return done(err, rows[0]); }); }) ); // route middleware to ensure user is logged in function isLoggedIn(req, res, next) { if (req.isAuthenticated()) return next(); res.sendStatus(401); } }; 

这是我的控制器类:

 class AuthenticateController { constructor(router, passport) { this.router = router; this.registerRoutes(); this.passport = passport; } registerRoutes() { this.router.post('/login/:username/:password', this.login.bind(this)); //this.router.get('/logout', this.logout.bind(this)); this.router.get('/content', this.content.bind(this)); } login(req, res) { this.passport.authenticate("local-login", { failureRedirect: "/login"}), res.redirect("/content"); } content(req, res ) { console.log(req.user); if (req.isAuthenticated()) { res.send("Congratulations! you've successfully logged in.") } else { res.sendStatus(401); } } isLoggedIn(req, res, next) { console.log(req.user); if (req.isAuthenticated()) return next(); res.sendStatus(401); } } module.exports = AuthenticateController; 

控制器获取路由器和护照完全configuration为从我的index.js参数。

//index.js

 var express = require('express') , cors = require('cors') , app = express() , passport = require('passport') , morgan = require('morgan'); require('./config/passport')(passport); // pass passport for configuration var bodyParser = require('body-parser'); app.use(bodyParser.json()); app.use(require('express-session')({secret: 'vidyapathaisalwaysrunning', resave: true, saveUninitialized: true })); app.use(passport.initialize()); app.use(passport.session()); app.use(cors()); var apiRouter = express.Router(); app.use('/api', apiRouter); // var apiV1 = express.Router(); apiRouter.use('/v1', apiV1); var authenticateApiV1 = express.Router(); apiV1.use('/auth', authenticateApiV1); var AuthenticateController = require('./controllers/authenticate'); var ac = new AuthenticateController(authenticateApiV1, passport); //pass in our fully configured passport //If I call this /login instead of the /auth/login/ in the Controller Class it works! //app.post("/login", // passport.authenticate("local-login", { failureRedirect: "/login"}), // function (req, res) { // res.redirect("/content"); // }); 

什么是工作,什么是不工作

身份validation一般正在工作。 在我发布的index.js中,你会看到app.post("/login", ...如果我调用这个,authentication成功,如果我尝试访问/ auth / content / req.user受限制内容 ,值(用户对象),我可以成功地调用req.isAuthenticated()

但是,如果我使用来自/auth/login/username/password的身份validation,当尝试访问受限制的内容时, req.user未定义的 。 我没有得到任何错误和/auth/login/username/password/ HTTP Code 301 – 'redirect到/内容的响应。

我目前不知道我在这里做错了什么,我很新的节点/快递/护照的主题..

希望有人有一个想法。 如果你需要别的东西来帮助我,只要在评论中提及它,我会尽我所能为你提供你所需要的一切。

谢谢

编辑:

我最近试图在login函数中读取req.user ,甚至在那里它是未定义的

 login(req, res) { this.passport.authenticate("local-login", { failureRedirect: "/login"}), console.log(req.user) //undefined res.redirect("/content"); } 

我想这可能是一些asynchronous的问题,我应该使用一些callback函数,但我不知道如何在我的login()

编辑2:

我面临的另一个问题是isLoggedIn()请求的集成。

如果我这样做:

 registerRoutes() { this.router.get('/', this.isLoggedIn, this.getUsers.bind(this)); this.router.get('/:id', this.getSingleUser.bind(this)); } 

它导致401 - Unauthorized

一个console.log(req.user);isLoggedIn()结果未定义。

但是如果我调用第一个路由而不调用isLoggedIn()并且执行console.log(req.user); 用户对象存在。

正确使用本地策略的passport身份validation可以如下所示:

function(req, res, next){ passport.authenticate('local-login', function(err, user, info){ if(err) return logger.log('error', err); if(user) req.login(user, function(err){ if(err) return next(err); return res.json({'success': true}); }); if(!user) return res.json({'error':true, 'message': info.message, 'type': info.type}); })(req, res, next);
}

请注意使用req.login()在会话中显式设置用户。

我唯一觉得奇怪的是你的路由声明是不同的。

AuthenticateController ,路由声明为:

 this.router.post('/login/:username/:password', ... 

而在index.js ,路由只是声明为

 app.post("/login", ... 

你的客户如何向服务器提交login凭证? 如果是通过forms,如教程 ,可能是有:username:password声明为路由参数,但通过forms梅西与护照发送?

尝试像index.js一样注册路线

 this.router.post('/login', ... 

编辑:我发现了另一个dicrepancy。 在AuthenticateControllerres.redirect("/content"); 不包含在callback中。 所以它在Authenticate完成运行之前正在执行。

index.js例子中,passport被用作路由中间件:

 app.post("/login", passport.authenticate("local-login", { failureRedirect: "/login"}), function (req, res) { res.redirect("/content"); }); 

passport.js它在callback中。 考虑在路由中声明它:

 registerRoutes() { this.router.post('/login', this.passport.authenticate("local-login", { failureRedirect: "/login"}), this.login.bind(this)); (...) } login(req, res) { res.redirect("/content"); } 

O,更好的是,为什么不使用passport's选项来声明成功和失败的redirect ,因为这似乎是你所做的一切:

 login(req, res) { this.passport.authenticate("local-login", { successRedirect: "/content", failureRedirect: "/login" }); } 

您将this.login.bind(this)作为中间件传递给this.router.post('/login/:username/:password', this.login.bind(this)); 但是login(req, res)只响应请求res.redirect("/content"); 即redirect到/内容

所以就像你说的那样,你需要提供一个callback函数,这个callback函数和从passports中间件返回的用户进行validationcallback函数。

 app.post("/login", passport.authenticate("local-login", { failureRedirect: "/login"}), function (req, res) { console.log(req.user); // log user in console res.json({user: req.user}); // send user as json response }); 

@divsingh提到的自定义callback是,如果你想明确地控制会话设置,错误消息和redirect请求。 任何其他信息可以在http://passportjs.org/docs下find