错误:使用passportjs / Express发送标题后无法设置标题

时间:2016-09-10 23:39:00

标签: node.js express passport.js

有问题的错误

  

错误:发送后无法设置标头。

server.js

// set up ======================================================================
var express = require('express')
    , app = express()
    , cookieParser = require('cookie-parser')
    , bodyParser = require('body-parser')
    , expressSession = require('express-session')
    , server = require('http').createServer(app)
    , passport = require('passport')
    , local = require('passport-local').Strategy
    , md5 = require('md5')
    , util = require('util')
    , flash = require('connect-flash')
    , port = 80
    , url = require('url')
    , db = require('./db');

// optimization ================================================================
var compress = require('compression');
app.use(compress());

// configuration ===============================================================
app.use(express.static('public'));
app.use(cookieParser());
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');

app.use(bodyParser.urlencoded({
    extended: true
}));
app.use(bodyParser.json());

app.use(expressSession({
    secret: 'key',
    resave: false,
    saveUninitialized: false
}));
app.use(passport.initialize());
app.use(passport.session());
app.use(flash());

// passport ====================================================================
passport.use(new local(
    function(username, password, done) {
        // asynchronous verification, for effect...
        process.nextTick(function () {
            db.findUserByName(username, function (err, user) {
                if (err) { done(err); }
                if (!user) { done(null, false, {message: 'Unknown user: ' + username})}
                if (md5(password) == user.password) {
                    done(null, user);
                } else {
                    done(null, false, {message: 'Invalid username or password'});
                }
            });
        });
    }
));
passport.serializeUser(function(user, done) {
    done(null, user.uuid);
});

passport.deserializeUser(function (id, done) {
    db.findUserByUUID(id, done);
});

// routes ======================================================================
require('./routes')(app, passport);

// launch ======================================================================
server.listen(port, function(){
    console.log('server started');
});

routes.js

var flash = require('connect-flash');

module.exports = function(app, passport) {

    app.get('/', function(req, res) {
        res.render('index', { num: 0, logged: false });
    });

    app.get('/login', function (req, res) {
        if (typeof req.user !== 'undefined') {
            // User is logged in.
            res.redirect('/');
        } else {
            req.user = false;
            var message = req.flash('error');
            if (message.length < 1) {
                message = false;
            }
            res.render('login', { logged: false, message: message });
        }
    });

    app.post('/login',
        passport.authenticate('local', {
            failureRedirect: '/login',
            failureFlash: true
        }),
        function(req, res) {
            res.redirect('/');
        }
    );

    app.get('/logout', function(req, res){
        req.logout();
        res.redirect('/');
    });


};

db.js

var MongoClient = require('mongodb').MongoClient;
var assert = require('assert');
var ObjectId = require('mongodb').ObjectID;
var url = 'mongodb://localhost:27017/db';

exports.findUserByName = function (username, callback) {
    MongoClient.connect(url, function(err, db) {
        var cursor = db.collection('players').find( { "name": username } );
        cursor.each(function(err, doc) {
            if (doc != null) {
                console.log('YES');
                callback(false, doc)
            } else {
                console.log('NO');
                callback(false, null);
            }
            db.close();
        });

    });
};

var findUserByUUID = function(uuid, db, callback) {
    var cursor = db.collection('players').find( { "uuid": uuid } );
    cursor.each(function(err, doc) {
        assert.equal(err, null);
        if (doc != null) {
            callback(false, doc)
        } else {
            callback(false, null);
        }
    });
};
exports.findUserByUUID = function (uuid, callback) {
    MongoClient.connect(url, function(err, db) {
        assert.equal(null, err);
        findUserByUUID(uuid, db, function(err, data) {
            callback(err, data);
            db.close();
        });
    });
};

我知道我两次调用done(),但是什么时候?我找不到了。 我想问题出在路线上,但我不知道在哪里。

1 个答案:

答案 0 :(得分:0)

passport.use()处理程序中,每次调用done()时,都需要return,以便后面的代码也不会被执行。

现在您有一系列if语句,每个语句都可以调用done(),但它们不是if/else语句,因此可以满足您正在测试的多个条件,因此可以不止一次调用done()

例如,更改此内容:

if (!user) { done(null, false, {message: 'Unknown user: ' + username})}

到此:

if (!user) { 
    done(null, false, {message: 'Unknown user: ' + username});
    return;
}

并且,改变这个:

if (err) { done(err); }

到此:

if (err) { 
    done(err); 
    return;
}

或者,您可以将所有内容都放入if/else if/else if/else,这样只有一个分支可以执行。 if语句满足条件然后执行时,就会出现问题。

现在,您的findUserByName()会在cursor.each()中调用其回调,因此可以多次调用它,这会让您多次拨打done()