노래하듯 이야기하고, 춤추듯 정복하라.

session정보 mysql에 저장하기 & passport 인증 구현 본문

프로그래밍/node.js

session정보 mysql에 저장하기 & passport 인증 구현

hyeoke 2018. 1. 6. 20:27

#서두

안녕하세요 모닝버드입니다. 오늘은 express-mysql-session 모듈을 설치하여 각 사용자의 세션 id를 mysql 데이터베이스에 저장하는 것과 passport의 passport-local 모듈을 사용하여 사용자 인증을 구현하는 것을 공부했습니다. 


#express-mysql-session

- npm에 모듈 설치하기

* 명령어 : npm install express-mysql-session --save



- .js 파일에서 모듈 임포트하기

새로운 const 변수에 require('express-mysql-session')을 통해 모듈으 임포트합니다. 그리고 session 설정의 store 부분에 새로운 MySQLStore() 객체를 할당하고 세부적인 설정을 해줍니다. 

{

host: 서버주소(domain),

port: 서버상의 mysql 포트 (default는 3306임),

user: 사용자(필자는 local서버를 사용므로 root라고 설정해줌),

password: mysql 비밀번호,

database: mysql 서버에서 생성한 database 이름

}

//express-session
const session = require('express-session');
const MySQLStore = require('express-mysql-session')(session);
app.use(session({
  secret: 'spemnv2395@#lsore*&@#oso3$%^#&#$@#$!',
  resave: false,
  saveUninitialized: true,
  store: new MySQLStore({
    host: 'localhost',
    port: 3306,
    user: 'root',
    password: 'newlife4829',
    database: 'o2'
  })
}));


- mysql의 o2데이터베이스에 저장된 세션 정보

특정 사용자로 로그인 했을 때 사용자의 username정보가 session data에 담겨집니다.



#passport 모듈 사용하기

- passport와 passport-local 모듈 설치하기

* 명령어 -> npm install passport --save

            -> npm install passport-local --save


< passport >

 

< passport-local >


- 필자가 구현한 소스

아래의 소스는 passport 모듈을 사용하여 login/logout/register을 처리하였다. passport가 성공적으로 작동하면 request 하위 메소드로 login(), logout(), user() 등의 새로운 녀석들이 생성된다. 세션에 접근하는 방법은 req.session.name 으로 접근할 수 이 작동순서는 passport.authenticate() -> passport.serializeUser() -> passport.deserializeUser() 순서로 작동한다. 필자는 console.log를 통하여 확인하였다.

////////////////////////// setting //////////////////////////
//express
const express = require('express');
const app = express();
//web server
app.listen(4004, () => console.log('hello 4004'));
//pug engine
app.set('view engine', 'pug');
app.set('views', './views');
app.locals.pretty = true;
//static
app.use(express.static('static'));
//body-parser
const bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({extended: true}));
//express-session
const session = require('express-session');
const MySQLStore = require('express-mysql-session')(session);
app.use(session({
  secret: 'spemnv2395@#lsore*&@#oso3$%^#&#$@#$!',
  resave: false,
  saveUninitialized: true,
  store: new MySQLStore({
    host: 'localhost',
    port: 3306,
    user: 'root',
    password: 'newlife4829',
    database: 'o2'
  })
}));
//pbkdf2
var pbkdf2Password = require('pbkdf2-password');
var hasher = pbkdf2Password();
//passport
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
app.use(passport.initialize());
app.use(passport.session());

/////////////////////////// route ///////////////////////////
//users
var users = [
  {
    username: 'junhyeok',
    password: 'hWB/AM3MHngW2N0tphhwhSjH1FagibQamovfQCvo7v2sCfxhDoMv8NEtZjHy3hv5gU242zMpymWIkptqVP5BoocBczcKPLrQ9WNpO+I9NjBUxOMgBazjg649mjc+3kbIomkMSWDxvdxshCXbhNiTmD7iNVeCou/RXTmSDv9mZ8M=',
    displayName: 'Jun',
    salt: 'nYMlZ4HIiz3A0LF2A9t4Hj8NdrdQm8OOLVKf8zoZj9NGOO0EDINhCJaxsocXflE3pBqMSATj5xY0nnmBHvg7IQ=='
  }
]

//main-page -> login 기능
app.get('/', (req, res) => {
  if(req.user && req.user.displayName){
    res.render('welcome', {dname: req.user.displayName});
  } else {
    res.render('main');
  }
});
//serializeUser -> LocalStrategy의 done(null, user);을 전달 받음
passport.serializeUser((user, done) => {
  console.log('serializeUser', user);
  done(null, user.username);
});
//deserializeUser => serializeUser의 done(null, user.username);을 전달받음
passport.deserializeUser((uname, done) => {
  console.log('deserializeUser', uname);
  for(var i=0; i 로그인 처리
passport.use(new LocalStrategy((username, password, done) => {
  var uname = username;
  var pwd = password;
  for(var i=0; i {
        if(hash === user.password){
            console.log('LocalStrategy', user);
            done(null, user);
        } else {
          done(null, false);
        }
      });
    }
  }
  done(null, false);
}));
app.post('/', passport.authenticate('local', {
    successRedirect: '/welcome',
    failureRedirect: '/welcome',
    failureFlash: false
  })
  // var uname = req.body.username;
  // var pwd = req.body.password;
  // for(var i=0; i {
  //       if(hash === user.password){
  //         req.session.displayName = user.displayName;
  //         req.session.save(() => {
  //           res.redirect('/welcome');
  //         });
  //       } else {
  //         res.render('failLogin');
  //       }
  //     });
  //   }
  // }
  // res.render('failLogin');
);

//welcome
app.get('/welcome', (req, res) => {
  if(req.user && req.user.displayName){
    res.render('welcome', {dname: req.user.displayName});
  } else {
    res.render('failLogin');
  }
});

//register
app.get('/register', (req, res) => {
  res.render('register');
});
app.post('/register', (req, res) => {
  var uname = req.body.username;
  var pwd = req.body.password;
  var dname = req.body.displayName;
  hasher({password: pwd}, (err, pass, salt, hash) => {
    var user = {
      username: uname,
      password: hash,
      displayName: dname,
      salt: salt
    }
    users.push(user);
    req.login(user, (err) => {
      req.session.save(() => {
        res.redirect('/welcome');
      });
    });
  });
});

//logout
app.get('/logout', (req, res) => {
  req.logout();
  // logout()으로 인한 session의 delete가 완료 된 후 redirect 실행
  req.session.save(() => {
    res.redirect('/');
  });
});


- passport가 작동되는 순서 


< console.log 코드 >


< console.log 결과 >

Comments