我的快递节点应用程序中有一个身份验证系统设置,但我在设置的护照身份验证时遇到了一些错误。例如,注册系统工作正常,我的验证系统(基本上检查用户/通行证组合是否对我学校的成绩簿登录有效)。但是,实际的护照登录(检查用户/通行证组合是否是我的mongoose数据库中的注册用户)无法正常运行。
关联 app.js
的一部分
//passport setup
app.use(passport.initialize());
app.use(passport.session());
passport.use(new LocalStrategy(function (username, password, done) {
User.findOne({username: username}, function (err, user) {
user.checkLogin(password, function (error, userIsValid) {
if (error) {
console.log('Error:');
return done(error);
}
if (userIsValid) {
console.log('Valid:');
}
});
});
}));
user.js的
var mongoose = require('mongoose');
var passportLocalMongoose = require('passport-local-mongoose');
var Schema = mongoose.Schema;
var bcrypt = require('bcrypt');
var User = new Schema({
username: String,
password: String,
studentID: {type: Number}
});
User.methods.checkLogin = function (password, callback) {
bcrypt.compare(password, this.password, function (error, same) {
if (error){
callback(error);
}
callback(same);
})
};
User.plugin(passportLocalMongoose);
module.exports = mongoose.model('User', User);
最后, index.js
var express = require('express');
var router = express.Router();
var passport = require('passport');
var User = require('../models/user');
var request = require('request');
var cheerio = require('cheerio');
//register
router.post('/register', function(req, res){
var username = req.body.username;
var password = req.body.password;
var studentID = req.body.studentID;
areCredentialsValid(username, password, function (statusBoolean) {
if (statusBoolean === true){
User.register(new User({
username: username,
password: password,
studentID: studentID
}), password, function (){
console.log('Registered:');
res.redirect('./');
res.end()
})
}else{
console.log('Invalid Credentials:');
res.redirect('./');
res.end()
}
});
});
function areCredentialsValid(username, password, callback){
if (typeof username !== 'undefined' && username !== null && username !== '' &&
typeof password !== 'undefined' && password !== null && password !== ''){
var cookie = {};
var responseBoolean = false;
var config = {
method: 'GET',
url: 'https://parents.mtsd.k12.nj.us/genesis/j_security_check',
headers: {
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36'
}
};
request(config, function (error, response, body) {
cookie = response.headers['set-cookie'];
console.log(cookie);
var config = {
method: 'POST',
url: 'https://parents.mtsd.k12.nj.us/genesis/j_security_check',
form: {
'j_username': username,
'j_password': password
},
headers: {
'Cookie': cookie,
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36'
}
};
request(config, function (error, response2, body) {
//console.log(response);
console.log(response2.headers);
if (response2.headers['location'] === '/genesis/parents?gohome=true'){
responseBoolean = true;
}else{
responseBoolean = false;
}
callback(responseBoolean);
return responseBoolean;
})
})
}
}
//login
router.post('/login', function(req, res) {
passport.authenticate('local', function (error, user, info){
if (user === false) {
// handle login error ...
console.log('failure');
} else {
// handle successful login ...
console.log('success');
}
});
});
module.exports = router;
感谢所有帮助。如果它更容易处理,可以找到源代码 here
更新: 因此,通过最新的建议,我得到以下输出:因此登录正在运行。然而,问题是,登录似乎是循环并识别用户一次,然后显示"无效登录"消息,而不仅仅是完成过程
答案 0 :(得分:2)
我发现了2个问题。
首先:
在app.js文件中,配置 LocalStrategy 后,您必须在检查用户凭据后调用 done 。
请参阅:
passport.use(new LocalStrategy(function (username, password, done) {
User.findOne({username: username}, function (err, user) {
user.checkLogin(password, function (error, userIsValid) {
// You function should return the user data, not just if it is valid or not.
if (error) {
console.log('Error:');
return done(error);
}
if (userIsValid) {
console.log('Valid:');
// call done here
return done(null, {_id: 123 /* data to represent the user*/});
} else {
// call done here when the user is not valid
console.log('Not Valid:');
return done(null, null, 'Invalid credentials (or something like this.)');
}
});
});
}));
二:
在您的登录路由配置中,您已经处理了调用 next 函数的错误,并且错误处理函数将捕获它。
//login
router.post('/login', function(req, res, next) {
passport.authenticate('local', function (error, user, info){
if (user === false) {
// handle login error ...
next(new Error('AuthenticationError'), req, res);
} else {
// handle successful login ...
res.redirect('/')
}
})(req, res, next);
});
编辑上次评论:
您不仅要检查用户是否不是false
,还要检查没有错误,请查看:
//login
router.post('/login', function(req, res, next) {
passport.authenticate('local', function (error, user, info){
// A error also means, an unsuccessful login attempt
if(error) {
console.error(error);
console.log('Failed login:');
// And do whatever you want here.
return next(new Error('AuthenticationError'), req, res);
}
if (user === false) {
// handle login error ...
console.log('Failed login:');
return next(new Error('AuthenticationError'), req, res);
} else {
// handle successful login ...
console.log('Successful login:');
res.redirect('./');
}
})(req, res, next);
});
这对我有用。
关于(req, res, next)
,它是中间件的参数。
所以你调用/ login路由,你得到了请求和响应,接下来,你调用了passport.authenticate
。此方法返回function(req, res, next)
,最后,您传递请求和响应。
请参阅从passport.authenticate
剪下的代码:
module.exports = function authenticate(passport, name, options, callback) {
...
// This is the function you call, when you do: (req, res, next)
return function authenticate(req, res, next) {
...
检查this以获取有关中间件的更多示例。
希望现在很清楚。
答案 1 :(得分:0)
问题是验证完成后您缺少verify callback
。请尝试以下代码:
在下面的代码中,当你创建一个LocalStrategy时,你在函数中有三个参数,即用户名,密码和完成。现在,当您的if (userIsValid)
有效时,您需要调用done(null, user)
的验证回调。因此,您可以在使用user
进行身份验证时获得passport.authenticate
。
passport.use(new LocalStrategy(function (username, password, done) {
User.findOne({username: username}, function (err, user) {
user.checkLogin(password, function (error, userIsValid) {
if (error) {
console.log('Error:');
return done(error);
}
if (userIsValid) {
console.log('Valid:');
//Below is the code you are missing
return done(null, user)
}
});
});
}));
passport.authenticate
中的参数是从验证回调中传递的参数。因此,在这种情况下,您需要在回调中只有两个参数,如下所示:
passport.authenticate('local', function (error, user){
//your-code
});