保护节点+ Postgres + Passport

时间:2016-11-22 05:23:36

标签: node.js postgresql security passport.js

我目前正在学习节点,postgres和护照,但我不确定如何保护我的应用程序和最佳实践。我不确定如何清理来自客户端和服务器的数据,或者是否需要,但我已经参数化了我的查询。任何帮助将不胜感激!为我的新手道歉。



var express = require('express');
var helmet = require('helmet')

var bodyParser = require('body-parser');
var cookieParser = require('cookie-parser');
var expressSession = require('express-session');

var passport = require('passport');
var passportLocal = require('passport-local');
var pg = require ('pg');
var bcrypt = require('bcryptjs');

var app = express();
app.use(helmet());
var server = require('http').createServer(app);
var io = require('socket.io')(server);

var config = {
  user: 'REDACTED',
  database: 'REDACTED',
  password: 'REDACTED',
  host: 'REDACTED',
  port: 5432,
  max: 10,
  idleTimeoutMillis: 30000,
};

var pool = new pg.Pool(config);
pool.on('error', function (err, client) {
  console.error('idle client error', err.message, err.stack)
})

app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(expressSession( {
  secret: process.env.SESSION_SECRET || 'secret',
  resave: false,
  saveUninitialized: false
}));

app.use(passport.initialize());
app.use(passport.session());

passport.use(new passportLocal.Strategy(function(username, password, done) {
  pool.connect(function(poolErr, poolClient, poolDone) {
    if(poolErr) {
      return console.error('pool client fetch error', poolErr);
    }

    poolClient.query('SELECT id, password FROM users WHERE username = $1', [username], function(queryErr, queryRes) {
      if(queryErr) {
        return console.error('query error', queryErr);
      }

      if(queryRes.rows[0] != undefined)
      {
          bcrypt.compare(password, queryRes.rows[0].password, function(compareErr, compareRes) {
            if(compareErr) {
              return console.error('bcrypt error', compareErr);
            }

            if(compareRes) {
                done(null, { id: queryRes.rows[0].id });
            } else {
                done(null, null);
            }

            poolDone();
          });
      } else {
        //user not found
        poolDone();
        done(null, null);
      }
    });
  });
  
}));


passport.serializeUser(function(user, done) {
  done(null, user.id);
});

passport.deserializeUser(function(id, done) {
  pool.connect(function(err, poolClient, poolDone) {
    if(err) {
      return console.error('pool client fetch error', err);
    }

    poolClient.query('SELECT * FROM users WHERE id = $1', [id], function(queryErr, queryRes) {
      if(queryErr) {
        return console.error('query error', queryErr);
      }

      if(queryRes.rows[0] != undefined)
      {
        done(null, { id: id, username: queryRes.rows[0].username, firstname: queryRes.rows[0].firstname, lastname: queryRes.rows[0].lastname });
      } else {
        //user not found
	done(null, null);
      }

      poolDone();
    });
  });
  
});

app.set('view engine', 'ejs');

app.get('/', function(req, res) {
  res.render('index', {
    isAuthenticated: req.isAuthenticated(),
    user: req.user
  })
});


app.get('/login', function(req, res) {
  res.render('login');
});

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

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

server.listen(8080);
console.log('Server is running...');




2 个答案:

答案 0 :(得分:1)

我没有看到太多问题,但这是我的2分来改进它。

使用压缩来缩小网络规模

app.use(require('compression'));

将serve-static用于静态文件,如图像或pdf

app.use(require('serve-static')('./public'))

使用中间件来控制需要身份验证的终端,例如查看/编辑个人资料,更改密码等

function authenticated(req, res, next) {
  if (req.isAuthenticated()) next();
  else {
    res.status(401).send('User not authenticated.');
    // or redirect to login
  }
}

app.get('/profile', authenticated, function(req, res) {
  res.render('profile', {
    req.user
  })
})

注销时包含会话销毁

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

答案 1 :(得分:1)

用于清理查询,您可以使用ORM,如sequelise