node.js - Passport 认证系统不工作

标签 node.js express passport.js

我在我的 Express Node 应用程序中设置了身份验证系统,但我设置的 Passport 身份验证遇到了一些错误。例如,注册系统运行良好,我的验证系统也运行良好(主要检查用户/通行证组合对于我学校的成绩册登录是否有效)。但是,实际的 Passport 登录(检查用户/通行证组合是否是我的 Mongoose 数据库中的注册用户)无法正常运行。

Relavent part of 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);

and finally, 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 .

UPDATE: So with the latest suggestions, I get the following output:enter image description here And thus the login is functioning. However, the thing is, the login seems to be looping and recognizing the user once, then showing the "invalid login" message rather than just finishing the process

最佳答案

我发现了 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有关中间件的更多示例。

希望现在一切都清楚了。

关于node.js - Passport 认证系统不工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43816058/

相关文章:

javascript - 多个根处理程序的目的是什么?

node.js - 测试 protected api 调用、mocha、supertest、node js、passport

javascript - 如何为 Passport 策略 callbackURL 设置当前主机?

node.js - 如何使用NodeJS连接从请求中提取请求http header

node.js - 运行 Mocha 测试时更改默认的 TypeScript 配置文件

javascript - 如何编写干净、模块化的 express.js 应用程序

javascript - `req.session.secret` 未在使用 Express-Session 的路由中定义

javascript - 在 typescript commonjs 中导入 jquery 和 bootstrap

javascript - 为使用 setTimeout() 的异步函数编写 Mocha 测试

javascript - 为已登录的用户手动创建 Passport session