NodeJS / express 4:在写入cookie时发送标题后不能设置标题

时间:2014-07-17 13:59:39

标签: node.js cookies express

我设置了一个模块,通过检查cookie来授予身份验证。 在每个路由上调用此模块,如果没有身份验证会话,它将比较cookie与数据库和授予会话。 每次成功比较后,模块都会更新数据库和cookie信息以及我收到错误的地方"错误:发送后不能设置标题。"

基本上我有我的路线"索引" :

var check_auth = require('./middleware/check_auth');
module.exports = function(app){

    app.get('/', check_auth, function(req, res){
        if(req.session.userid){
            res.render('index', { title: 'AUTH'});  
        }else{
            res.render('index', { title: 'NOT AUTH'});
        }
    });
};

现在我的模块check_auth:

var mysql = require('mysql');
var crypto = require('crypto');
var bcrypt = require('bcrypt');
var pool = mysql.createPool({
    host: 'localhost',
    user: 'root',
    password: '****',
    database: 'nodejs'  
});

function check_auth(req, res, next){
    if(!req.session.userid){
        var cookie_auth = req.signedCookies.auth;
        var cookie_db_id = req.signedCookies.db_id;
        if(cookie_auth && cookie_db_id){
            pool.getConnection(function(err, conn) {
                var db_id = false;
                query = conn.query('SELECT * FROM users WHERE id = ?', [cookie_db_id]);
                query.on('error', function(err){
                    throw err;
                });
                query.on('result', function(row){
                    db_id = row.id;
                    db_cookie = row.cookie;
                    db_username = row.username;
                });
                query.on('end', function(result){
                    if(db_id && cookie_auth == db_cookie){
                        console.log("OK");
                        req.session.username = db_username;
                        req.session.userid = db_id;
                        var salt = bcrypt.genSaltSync(10);
                        var crypt = crypto.randomBytes(64).toString();
                        var hash = bcrypt.hashSync(crypt, salt);                    
                        res.cookie('auth', hash, { expires: new Date(Date.now() + (1000 * 60 * 60 * 24 * 365)), signed: true, httpOnly: true, secure: true });                          
                        res.cookie('db_id', db_id, { expires: new Date(Date.now() + (1000 * 60 * 60 * 24 * 365)), signed: true, httpOnly: true, secure: true });
                        pool.getConnection(function(err, conn) {                        
                            conn.query('UPDATE users SET cookie = (?) WHERE id = ?', [hash, db_id], function(err, info){
                                if(err) throw err;
                            });
                        });
                        conn.release();                             
                    }
                });
            });
        }
    }
    next();
}

module.exports = check_auth;

错误出现在以下行:

res.cookie('auth', hash, { expires: new Date(Date.now() + (1000 * 60 * 60 * 24 * 365)), signed: true, httpOnly: true, secure: true });                          
res.cookie('db_id', db_id, { expires: new Date(Date.now() + (1000 * 60 * 60 * 24 * 365)), signed: true, httpOnly: true, secure: true });

这个错误是因为我将我的cookie写入mysql的异步函数还是与模块/路由有关? 无论如何,欢迎任何解决方案。

2 个答案:

答案 0 :(得分:3)

由于异步性质,next很可能会立即被调用。将回调移到end处理程序中。

function check_auth(req, res, next) {
    if (!req.session.userid) {
        var cookie_auth = req.signedCookies.auth;
        var cookie_db_id = req.signedCookies.db_id;
        if (cookie_auth && cookie_db_id) {
            pool.getConnection(function(err, conn) {
                if(err) return next(err);
                var db_id = false;
                query = conn.query('SELECT * FROM users WHERE id = ?', [cookie_db_id]);
                query.on('error', function(err) {
                    return next(err);
                });
                query.on('result', function(row) {
                    db_id = row.id;
                    db_cookie = row.cookie;
                    db_username = row.username;
                });
                query.on('end', function(result) {
                    if (db_id && cookie_auth == db_cookie) {
                        console.log("OK");
                        req.session.username = db_username;
                        req.session.userid = db_id;
                        var salt = bcrypt.genSaltSync(10);
                        var crypt = crypto.randomBytes(64).toString();
                        var hash = bcrypt.hashSync(crypt, salt);
                        res.cookie('auth', cookie_auth, {
                            expires: new Date(Date.now() + (1000 * 60 * 60 * 24 * 365)),
                            signed: true,
                            httpOnly: true,
                            secure: true
                        });
                        res.cookie('db_id', db_id, {
                            expires: new Date(Date.now() + (1000 * 60 * 60 * 24 * 365)),
                            signed: true,
                            httpOnly: true,
                            secure: true
                        });
                        pool.getConnection(function(err, conn) {
                            conn.query('UPDATE users SET cookie = (?) WHERE id = ?', [hash, db_id], function(err, info) {
                                if (err) throw err;
                            });
                        });
                        conn.release();
                    }
                    return next();
                });
            });
        }
    } else {
        next();
    }
}

答案 1 :(得分:0)

是的,您对问题的异步性质是正确的。一个简单的解决方法是在查询结束时调用呈现功能:

function check_auth(req, res, next){
if(!req.session.userid){
    var cookie_auth = req.signedCookies.auth;
    var cookie_db_id = req.signedCookies.db_id;
    if(cookie_auth && cookie_db_id){
        pool.getConnection(function(err, conn) {
            var db_id = false;
            query = conn.query('SELECT * FROM users WHERE id = ?', [cookie_db_id]);
            query.on('error', function(err){
                throw err;
            });
            query.on('result', function(row){
                db_id = row.id;
                db_cookie = row.cookie;
                db_username = row.username;
            });
            query.on('end', function(result){
                if(db_id && cookie_auth == db_cookie){
                    console.log("OK");
                    req.session.username = db_username;
                    req.session.userid = db_id;
                    var salt = bcrypt.genSaltSync(10);
                    var crypt = crypto.randomBytes(64).toString();
                    var hash = bcrypt.hashSync(crypt, salt);                    
                    res.cookie('auth', cookie_auth, { expires: new Date(Date.now() + (1000 * 60 * 60 * 24 * 365)), signed: true, httpOnly: true, secure: true });                           
                    res.cookie('db_id', db_id, { expires: new Date(Date.now() + (1000 * 60 * 60 * 24 * 365)), signed: true, httpOnly: true, secure: true });
                    pool.getConnection(function(err, conn) {                        
                        conn.query('UPDATE users SET cookie = (?) WHERE id = ?', [hash, db_id], function(err, info){
                            if(err) throw err;
                        });
                    });
                    conn.release();
                    if(req.session.userid){
                        res.render('index', { title: 'AUTH'});  
                    }else{
                        res.render('index', { title: 'NOT AUTH'});
                    }
                }
            });
        });
    }
}
next();}`