ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 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") });
    1. .env 환경변수에 저장한 db주소와 계정 정보등을 불러와서 사용
    2. 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 }
    }));
    1. 세션미들웨어 설정 : 로그인 정보를 세션에 저장하고 유지하기위해
    2. 세션정보는 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());
    1. 'passport' 미들웨어 불러오기
    2. 'passprot'에서 'Strategy'는 인증 '방식'을 의미, 'LocalStratege'는 아이디, 비번으로 로그인하는 방식
    3. 인증정보를 세션에 저장
    4. 'passport' 인증 중 발생하는 메세지(오류, 인증실패 등)를 'flash' 형식으로 저장하므로 미리 사용 설정
    5. '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);
    });
    1. 'passport' 로그인을 성공하여 얻은 유저정보 객체는 'serializeUser'의 첫번째 인자 'user'로 전달
      • done()은 이중 필요한 것만 골라서 req.session.passport.user에 저장
    2. 위의 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: '비밀번호를 확인해주세요' }) }
    		})
    	}
    ));
    1. 기본적으로  form의 name='username' 필드 입력값을 아이디로 사용하나 여기서는 'email'을 아이디로 사용
    2. mongoDB의 User스키마에서 해당 username을 검색, 'user' 라는 객체로 반환
    3. user가 없으면 인증실패(false), flash()에 '이메일을 확인해주세요'라는 메세지 저장
    4. DB에서 찾은 'user.password'가 form에서 받은 'password'와 같으면 성공, 'user' 반환 => 앞의 serializeUser()의 첫번째 인자로 전달
    5. 'password'가 일치하지 않으면 인증실패(false), flash()에 '비밀번호를 확인해주세요'메세지 저장
    6. req.flash()로 메세지를 불러올 수 있음
    router.post(
    	'/auth',
    	passport.authenticate( 'local', { failureRedirect: '/', failureFlash: true }),
    	function(req, res) { req.session.save(function(){ res.redirect('/') }) }
    );
    1. form에서 로그인요청이 들어왔을때(action='/auth') passport 인증 실행
    2. 실패시 실패메세지와 함께 '/'로 이동
    3. 성공시 세션을 저장하고 '/'로 이동
    4. 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 } )
    	}
    });
    1. '/' 요청이 왔을때 passport() 인증이 된 상태라면 'loggedIn' 페이지 보여줌
    2. 이때 유저정보는 req.session.passport.user 객체로 저장되므로 필요에 맞게 꺼내쓰면 됨
    3. 인증이 안되었다면 'notLoggedIn' 페이지 보여줌
    4. req.flash()로 플래쉬메시지를 불러온후 에러메시지가 존재하면 페이지에 인자로 함께 보냄
Designed by Tistory.