2014-07-17 62 views
0

我正在設置一個模塊,通過檢查cookie來授予認證。 這個模塊在每個路由上被調用,如果沒有認證的會話,它會比較cookie和數據庫和授予會話。 每次成功比較後,模塊將更新數據庫和cookie信息,這就是我收到錯誤的地方「錯誤:發送後無法設置標題」。NodeJS/express 4:在寫入cookie時發送它們後不能設置標題

所以basicly我有我的路線 「指數」:

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的異步函數中,或者是與它有關的東西模塊/路線? 無論如何,任何解決方案都是受歡迎的。

+0

由於異步性質,很可能會立即調用next。將你的回調移到你的'end'處理器中。 –

+0

謝謝!工作正常!你可以添加一個答案,所以我可以接受它 –

+0

也不要在您的應用程序的回調中拋出錯誤。通過執行'return next(err);'來使用node.js/express的錯誤傳遞方式。 – AlexandruB

回答

2

由於異步性質,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(); 
    } 
} 
+0

嘿,對不起,它第一次工作我搬了下一個,但現在我清除了我的瀏覽器的所有會話/ cookie它就像等待下一個永遠不會來的聲明。即使我有cookie但沒有會話 –

+0

編輯它,請嘗試將它移到if語句之外。如果您要依靠多個操作,則最有可能還需要多個。 –

+0

是的,我還在第一個'if'中做了下一個陳述(sry沒有在我的評論中提到過)。無論如何,我明白了。必須在所有if語句中添加'next()')TY –

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();}` 
+2

在一個函數中執行所有邏輯是一種不好的做法,特別是當Node.js允許智能中間件結構和代碼重用時。 – AlexandruB

+0

@AlexandruB同意,這是我爲什麼使用路由模塊的主要目的。 –

相關問題