-
passport 미들웨어를 이용한 로컬로그인node.js 2020. 11. 1. 23:46
온갖 종류의 로그인방식을 처리해주는 'passport' 모듈을 설치하여 로그인을 쉽게(?) 구현
./roots/index.js
require('dotenv').config(); const dbURL = process.env.dbURL; const mongoose = require('mongoose'); mongoose.set('useCreateIndex', true); mongoose.connect(dbURL,{ useNewUrlParser: true, useUnifiedTopology: true }); mongoose.connection.on('error', console.error.bind(console, "connection error:")); mongoose.connection.once('open', () => { console.log("DB connected") });
- .env 환경변수에 저장한 db주소와 계정 정보등을 불러와서 사용
- mongoDB 연결
const session = require('express-session'); const connectMongo = require('connect-mongo')(session); router.use(session({ secure: true, HttpOnly: true, secret: 'fasdfsadgsadgffhfjkhkdf', resave: false, saveUninitialized: true, store: new connectMongo({url: dbURL,collection: 'sessions'}), cookie: { maxAge: 1000*60*60*10*10 } }));
- 세션미들웨어 설정 : 로그인 정보를 세션에 저장하고 유지하기위해
- 세션정보는 mongoDB에 저장
const passport = require('passport') , LocalStrategy = require('passport-local').Strategy; router.use(passport.initialize()); router.use(passport.session()); const flash = require('connect-flash'); router.use(flash());
- 'passport' 미들웨어 불러오기
- 'passprot'에서 'Strategy'는 인증 '방식'을 의미, 'LocalStratege'는 아이디, 비번으로 로그인하는 방식
- 인증정보를 세션에 저장
- 'passport' 인증 중 발생하는 메세지(오류, 인증실패 등)를 'flash' 형식으로 저장하므로 미리 사용 설정
- 'flash'는 휘발성 메세지이며 {key,value} 형태로 세션에 저장됨, 한번 사용되면 자동삭제
passport.serializeUser(function(user, done) { done(null, { nick: user.nick, hospital: user.hospital[0].name }); }); passport.deserializeUser(function(user, done) { done(null, user); });
- 'passport' 로그인을 성공하여 얻은 유저정보 객체는 'serializeUser'의 첫번째 인자 'user'로 전달
- done()은 이중 필요한 것만 골라서 req.session.passport.user에 저장
- 위의 done()의 두번째인자(req.session.passport.user)는 다음 'deserializeUser()'의 첫번째인자로 전달
- done()의 두번째인자 user가 'passport' 함수의 req.user가 됨
passport.use(new LocalStrategy( usernameField = 'email', function(username, password, done) { User.findOne({ email: username }, (err, user) => { if (err) { return done(err) } if (!user) { return done(null, false, { message: '이메일을 확인해주세요' }) } if (user.password === password ) { return done(null, user) } else { return done(null, false, { message: '비밀번호를 확인해주세요' }) } }) } ));
- 기본적으로 form의 name='username' 필드 입력값을 아이디로 사용하나 여기서는 'email'을 아이디로 사용
- mongoDB의 User스키마에서 해당 username을 검색, 'user' 라는 객체로 반환
- user가 없으면 인증실패(false), flash()에 '이메일을 확인해주세요'라는 메세지 저장
- DB에서 찾은 'user.password'가 form에서 받은 'password'와 같으면 성공, 'user' 반환 => 앞의 serializeUser()의 첫번째 인자로 전달
- 'password'가 일치하지 않으면 인증실패(false), flash()에 '비밀번호를 확인해주세요'메세지 저장
- req.flash()로 메세지를 불러올 수 있음
router.post( '/auth', passport.authenticate( 'local', { failureRedirect: '/', failureFlash: true }), function(req, res) { req.session.save(function(){ res.redirect('/') }) } );
- form에서 로그인요청이 들어왔을때(action='/auth') passport 인증 실행
- 실패시 실패메세지와 함께 '/'로 이동
- 성공시 세션을 저장하고 '/'로 이동
- successRedirect:'/'로 간단하게 쓸수 있으나 세션이 저장되기전에 이동해버리는 오류가 발생할수 있어서 이렇게 작성함
router.get('/', function(req, res) { if(req.isAuthenticated()) { res.render( 'loggedIn' ) } else { let note= null; let flashMessage = req.flash(); if( flashMessage.error ) { note= flashMessage.error[0] } res.render( 'notLoggedIn', { note: note } ) } });
- '/' 요청이 왔을때 passport() 인증이 된 상태라면 'loggedIn' 페이지 보여줌
- 이때 유저정보는 req.session.passport.user 객체로 저장되므로 필요에 맞게 꺼내쓰면 됨
- 인증이 안되었다면 'notLoggedIn' 페이지 보여줌
- req.flash()로 플래쉬메시지를 불러온후 에러메시지가 존재하면 페이지에 인자로 함께 보냄