Passport-local 사용법 (nodejs)

박주홍·2022년 2월 25일
0
post-thumbnail

passport-local

passport-local는 nodejs에서 로그인을 간편하게해주고, 브라우저 쿠키에 세션과 웹서버에 세션을 저장해서 Authorization(인가)를 해줄 수 있도록 도와주는 라이브러리다. passport로 로그인처리를 하는 법을 블로깅해보도록 하겠다.



필요한 모듈들

 	"body-parser": "^1.19.2",
    "cookie": "^0.4.2",
    "cookie-parser": "^1.4.6",
    "cors": "^2.8.5",
    "express": "^4.17.3",
    "express-session": "^1.17.2",
    "install": "^0.13.0",
    "nodemon": "^2.0.15",
    "npm": "^8.5.1",
    "passport": "^0.5.2",
    "passport-local": "^1.0.0",
    "passport-session": "^1.0.2",
    "session-file-store": "^1.5.0"
	// session-file-store는 다른 DB로 대체가능

모듈 require

필요한 모듈을 require해준다.

const express = require("express");
// session 사용할때 필요
const session = require('express-session');
// session을 저장할 때 필요
const FileStore = require('session-file-store')(session);
// cors 고려해서 응답시 필요
const cors = require('cors');
// 클라이언트의 쿠키를 웹서버가 파싱할 수 있도록 require
const cookieParser = require('cookie-parser');
// 클라이언트에서 post요청을 했을때 req.body로 데이터를 받을 수 있도록 require
const bodyParser = require("body-parser");
// passport와 passport-local
const passport = require('passport');
const Strategy = require('passport-local').Strategy;


const app = express();





필요한 미들웨어들


app.use(cors({
  origin: true,
  credentials: true // 요청에 쿠키를 넣고싶으면 이 옵션 사용
}));


// body parse
app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.json())
app.use(express.urlencoded({ extended: true }));

app.use(cookieParser());


// 이 세션함수는 반드시 passport.session() 전에 사용해야한다
app.use(session({
  secret: 'secret key',
  resave: true,
  saveUninitialized: false,
  secure: false, 
  store: new FileStore() // 세션을 저장할 store를 할당해줌
}));

// passport 초기화
app.use(passport.initialize());
app.use(passport.session());





Strategy, 전략 세우기

Strategy, 전략이란 말이 어색할 것이다.
단순히 로그인을 어떻게 구현할 것이라고 전략을 세운다고 생각하면 될 것 같다.

let strategy = new Strategy({
  usernameField: 'email', 
  passwordField: 'password', 
  session: true, // session에 저장 여부
  passReqToCallback: true, // 이 옵션을 설정하면 아래 콜백 함수의 첫번째 파라미터로 req 객체 전달됨
}, (req, email, password, done) => {
  if (email === 'test@naver.com' && password === '1234') {
    let userInfo = {
      email: 'test@naver.com',
      name: '홍길동',
      birth: '1102.05.29'
    }
    done(null, userInfo);
  } else {
    done(null, false, { message: "Incorrect ID/PW" });
  }
});
passport.use(strategy);





passport.serializeUser 와 deserializeUser

serializeUser는 로그인 성공을 하면 세션을 저장해주는 코드이고,
deserializeUser는 세션이 있을때 세션정보를 꺼내주는 코드라고 생각하면된다.
세션이 있다면 req.user로 접근이 가능하다.

passport.serializeUser(function (user, done) {
 console.log("serializeUser user : ", user);
 done(null, user);
}); // 로그인 성공했을때 호출됌
passport.deserializeUser(function (user, done) {
 console.log("deserializeUser user : ", user);
 done(null, user); // 여기 유저는 serializeUser에서 done으로 넘겨준 user임
 // 여기서 최종으로 넘기면 세션에 저장되서 req.user로 사용가능하다?
}); // 모든요청마다 호출됌





로그인 처리 라우터

app.post('/login', (req, res, next) => {
  passport.authenticate('local', {
    successRedirect: '/',
    failureRedirect: '/' },
    (err, user, message) => {
      if (user !== undefined) {
        req.logIn(user, (err)=>{
          if(err)return next(err);
          res.json({ result: 'User have sesseion' });
        });
      }
    }
  )(req, res, next);
});

passport.authenticate의 첫번째 인자는 local전략을 사용하겠다란 말이고,
두번째 객체는 로그인 성공, 실패시 어디 Path로 갈 것인지 정하는 옵션이고,
세번째 인자인 콜백함수는 로그인성공시 serializeUser가 실행되고나서 그 유저 정보를 콜백함수 두번째 인자에서 받아볼 수 있고, 로그인 실패시 콜백함수 첫번째 인자에서 err을 받아볼 수 있다.


로그아웃

app.get('/logout', (req, res) => {
  // console.log('/logout', req.session);
  req.logOut();
  res.json({ result: 'User have not sesseion' });
})



Authorization

app.get('/', (req, res) => {
  console.log('req.user', req.user);
  res.json({ userInfo: req.user});
});

user정보를 클라이언트에서 바로 쏴서 클라이언트에서 유저정보가 없으면 Authorization을 안해줘도되고, 유저정보가 있으면 Authorizaion을 해줘도 되는 즉, Authorization처리를 클라이언트에서 해줘도 되고 다음과 같이 서버에서 해줘도 된다.

app.get('/', (req, res) => {
	if(req.user === undefined){
    	res.status(400).send('로그인해주세요');
    }else{
    	res.status(200).send('Authorizaion해주세요')
    }
})





전체코드

const express = require("express");
const session = require('express-session');
const FileStore = require('session-file-store')(session);
const cors = require('cors');
var cookieParser = require('cookie-parser');
// var cookie = require('cookie');
const bodyParser = require("body-parser");

const app = express();

// middleware list
app.use(cors({
  origin: true,
  credentials: true
}));
/*
  Credentials(인증서) 이 있는 CORS 요청은 Client와 Server
  둘다 Credentials를 사용하겠다는 속성을 설정해줘야 통신이 가능
*/

app.use(express.urlencoded({ extended: true }));
app.use(cookieParser());
// 이 세션함수는 반드시 passport.session() 전에 사용해야한다
app.use(session({
  secret: 'secret key',
  resave: true,
  saveUninitialized: false,
  secure: false, // 이건 뭘까
  store: new FileStore()
}));

const passport = require('passport');
const Strategy = require('passport-local').Strategy;

// passport.use(strategy); 이후에 미들웨어를 사용해야함
app.use(passport.initialize());
app.use(passport.session());

let strategy = new Strategy({
  usernameField: 'email', // input name
  passwordField: 'password', //input name
  session: true, // session에 저장 여부
  passReqToCallback: true, // 이 옵션을 설정하면 아래 콜백 함수의 첫번째 파라미터로 req 객체 전달됨
}, (req, email, password, done) => {
  if (email === 'test@naver.com' && password === '1234') {
    let userInfo = {
      email: 'test@naver.com',
      name: '홍길동',
      birth: '1102.05.29'
    }
    done(null, userInfo);
  } else {
    done(null, false, { message: "Incorrect ID/PW" });
  }
});
passport.use(strategy);


/*
 serializeUser는 로그인 성공을 하면 세션을 저장해주는 코드이고,
 deserializeUser는 세션이 있을때 세션정보를 꺼내주는 코드라고 생각하면된다.
 세션이 있다면 req.user로 접근이 가능하다.
*/

passport.serializeUser(function (user, done) {
  console.log("serializeUser user : ", user);
  done(null, user);
}); // 로그인 성공했을때 호출됌
passport.deserializeUser(function (user, done) {
  console.log("deserializeUser user : ", user);
  done(null, user); // 여기 유저는 serializeUser에서 done으로 넘겨준 user임
  // 여기서 최종으로 넘기면 세션에 저장되서 req.user로 사용가능하다?
}); // 모든요청마다 호출됌

app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json()); // 요놈이 들어가야 한다.

app.get('/', (req, res) => {
  console.log('req.user', req.user);
  // passport.authenticate('local', {}, (err, user, message)=>{
  //   console.log(user);
  // })
  res.json({ userInfo: req.user});
});


// passport.authenticate를 하면 req.login()함수가 자동 실행됌
app.post('/login', (req, res, next) => {
  console.log('/login', req.session);
  passport.authenticate('local', {
    successRedirect: '/',
    failureRedirect: '/' },
    (err, user, message) => {
      console.log("req.user : "+ JSON.stringify(req.user));
      if (user !== undefined) {
        console.log('app.post : ', user);
        req.logIn(user, (err)=>{
          if(err)return next(err);
          res.json({ result: 'User have sesseion' });
        });
      }
    }
  )(req, res, next);
});

app.get('/logout', (req, res) => {
  // console.log('/logout', req.session);
  req.logOut();
  res.json({ result: 'User have not sesseion' });
})


app.listen(80, () => {
  console.log('80포트 실행됌')
})
profile
고통없는 성장은 없다고 할 수 있겠다....

0개의 댓글