노드JS [Express]

[passport 패스포트] 노드JS passport 정리글

훈츠 2020. 7. 1. 17:31
반응형

 

안녕하세요. 훈츠입니다. 금일은 Passport  관해 정리 합니다. 세션을 가지고 인증작업을 하였을때보다 좀더 는 보안을 강화 할수있고, 무엇보다  구글로 로그인하기, 페이스북으로 로그인하기 같은 기능을 손쉽게 가능하도록 도와줍니다.  

 

강의 출처는 opentutorials.org/module/3655

 

WEB5 - Express passport.js

수업소개 이 수업은 Node.js Express의 인증 미들웨어인 Passport.js의 사용법을 알려드리는 수업입니다.  수업대상 로그인/로그아웃/접근제한과 같은 인증 기능을 구현하고 싶은 분에게 필요한 수업��

opentutorials.org

생활 코딩의 이고잉님 강좌를 참조하였습니다. 


목 차

  • 패스포트 동작 설명 및 설치 

  • 패스포트 인증 관련 순서

  • 전체 코드 공유 


패스포트 동작 설명 및 설치방법

패스포트는 익스프레스 프레임 워크 진영에서, 개발된 라이브러리 입니다. 대략 300여가지의 전략이라는 이름으로 다양한 로그인 방법을 제시 하고 있습니다. 그중 가장 기본이 되는 로컬 스토리지 전략 ( 아이디, 비밀번호 )에 대해 설명 드리도록 하겠습니다. 

 

사이트 : www.passportjs.org  

 

Passport.js

Simple, unobtrusive authentication for Node.js

www.passportjs.org

패스포트 설치 

 npm install -s passport

 

전략 설치 하기 

 npm install -s passport-local (로컬 방식 으로 로그인)

 npm install -s connect-flash (플래시 메시지)

 

패스포트를 설치하고, 로컬 전략과 플래시 메시지를 사용하기 위해서 플래시 메시지를 설치 합니다. 


패스포트 인증 관련 순서

전체적인 패스포트의 흐름 입니다.

 

 1. passport 전략 결정 하기 ( 로컬 전략 ) 

 

 2. passport 초기화 및 세션 사용등록 

 

 3. 패스포트 로그인 체크 (아이디와 패스워드를 검증) Done 함수 이용 

 

 4. 씨리얼라이즈 유저 

    로그인 성공하면, 최초 1회만 동작하며 콜백함수의 user 인자로 넘어온값을 done 함수의 인자로 전달하면, 디시리얼라이즈의 콜백 함수의 id로 넘겨 줍니다.  

 

 5. 디씨리얼 라이즈유저 

    콜백함수로 넘어온 id를 key 값으로, 데이터베이스 혹은 저장된 사용자 정보를 검색해서 done 함수의 인자로 전달하면 이후 부터는 화면이 리로드 될때마다 디씨리얼 라이즈가 호출 되면서 확인 합니다. 

 

 6. 접근제어를 위한 유저호출 

    로그인 이후에는 request.user 라는 객체가 추가되어 그안에 로그인 데이터가 저장 됩니다. 로그아웃 되면 request.user 의 값은 undefined 값이 됩니다.

 

 7. 플래시 메시지

    플래시 메시지는 패스포트에서 내부적으로 사용하고 있는 프로그램 입니다. 사용 용도는 로그인 실패시혹은 성공시 일회성 메시지를 띄워주기 위함입니다. 

 

 8. 로그아웃 

     request.logout() 후에 세션을 이용할때와 마찬가지로 삭제후 리다렉션을 해야 합니다. 다음코드를 참조하세요. requset.session.save(function(err) { res.redirect('/'); } ))


1. 패스포트 전략 결정 하기 (로컬 전략)

전통적인 ID 그리고 Password 로 로그인하는 방법 입니다. 패스포트 사이트에서 구성탭을 참조하세요. 

 

1
2
3
4
5
6
7
//Hoons Blog---https://rain2002kr.tistory.com------------------------------------------------------------------코드///
 
//패스포트 로컬 전략 
var passport = require('passport'), 
    LocalStrategy = require('passport-local').Strategy;
 
 
cs

 


2. 패스포트 초기화 및 세션 사용 설정

패스포트를 사용하기 위해서 익스프레스앱에 사용 등록을 합니다. 

 

1
2
3
4
5
6
7
//Hoons Blog---https://rain2002kr.tistory.com------------------------------------------------------------------코드///
 
//passport session 사용 
app.use(passport.initialize());
app.use(passport.session());
 
 
cs

 


3. 패스포트 로그인 체크

아이디와 패스워드를 검증하고 Done 함수를 호출 합니다. 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
//Hoons Blog---https://rain2002kr.tistory.com------------------------------------------------------------------코드///
 
//패스포트 사용 
passport.use(new LocalStrategy(
    //사용자가 필드를 변경시키고 싶으면 아래처럼 추가 합니다. 
    {
        usernameField: 'email',
        passwordField: 'password'
    },
    function(username, password, done) {
        console.log('LocalStrategy ' + username, password)
        if(username === authDate.email){
            console.log('1');
            if(password === authDate.password){
                console.log('2');
                return done(null, authDate); //아이디와 비번이 일치할때, done 함수로 유저데이터를 넣어주면 session에 등록됩니다. 
            } else {
                console.log('3');
                return done(nullfalse, { message: 'Incorrect password.' });      
            }
        } else {
            console.log('4');
            return done(nullfalse, { message: 'Incorrect username.' });
        }
    }
  ));
 
 
cs

4. 씨리얼라이즈 유저 호출

아이디와 패스워드가 일치후, done 함수에 true값과 유저 데이터가 들어오면 최초 1회 SerializeUser()함수가 호출 됩니다. 이때 done 함수를 호출하고, 그안에 식별값을 넣어주면 세션에 passport 항목에 내용이 추가 됩니다. 

 

1
2
3
4
5
6
7
8
9
//Hoons Blog---https://rain2002kr.tistory.com------------------------------------------------------------------코드///
 
//Passport 로그인이 성공되면, 그곳에서 입력한 데이터가 이곳에 콜백의 유저로 넘어 옵니다. 
passport.serializeUser(function(user, done) {
    console.log('serializeUser :' + user.email);
    done(null, user.email);
  });
 
 
cs

5. 디씨리얼라이즈 유저 호출

씨리얼라이즈 유저가 호출된 이후부터 화면이 리로드 될때마다 DeserializeUser() 함수가 호출 됩니다. 이때 씨리얼라이즈유저 함수에서 등록해둔 식별자값은 콜백함수의 id값으로 들어오는데 이 id값을 가지고 데이터베이스의 내용에서 find 함수를 이용하여 값을 가져오는 로직을 구성 하면 됩니다. 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
//Hoons Blog---https://rain2002kr.tistory.com------------------------------------------------------------------코드///
 
//한번 통신하고 나면,웹이 리로드될때마다 이곳이 호출되어서 이곳에서 DB의 유저값을가져와 비교합니다.   
//심플한 테스트를 위해,db 에 있는값이 아닌 위의 값을 넣어줍니다. 
passport.deserializeUser(function(id, done) {
    console.log('deserializeUser :',id);
    done(null, authDate);
    /*  User.findById(id, function(err, user) {
       done(err, user);
     }); */
});
 
 
cs

6. 접근제어를 위한 유저 호출

패스포트를 이용하여 로그인이 완료되면, 패스포트는 req.user 를 등록 합니다.  index 화면이나 기타 로그인 체크를 하기위해서 다음 user 항목에 내용이 있다면 로그인, 없다면 로그아웃으로 판단 하는 로직을 추가 합니다. 참고로 로그아웃을 하게 되면 user 안의 데이터는 없습니다. 

 

1
2
3
4
5
6
7
8
9
//Hoons Blog---https://rain2002kr.tistory.com------------------------------------------------------------------코드///
 
//WEB PAGE Content load 
router.get('/', function (request, response) {
    //패스포트를 이용해서 로그인에 성공하면, requset.user 로 값이 들어옵니다.
    console.log('root page: ', request.user);
    //이하코드 생략
 
 
cs

위에 해당하는 코드를 로그인 확인 하는 부분에 아래와 같이 접목 했습니다. 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//Hoons Blog---https://rain2002kr.tistory.com------------------------------------------------------------------코드///
 
module.exports = {
    IsOwner : function (request,response){
    if(request.user){   //유저 유무에 따라 로그인 및 로그아웃을 판단 합니다. 
        return true;
    } else {
        return false;
    }
},
    StatusUI : function (request,response){
    var authStatusUI= `<a href="/auth/login">login</a>`
    if(this.IsOwner(request,response)){
        console.log(request.user.nickname);    
        authStatusUI= `${request.user.nickname} | <a href="/auth/logout">logout</a>`
    } 
        return authStatusUI;
    }
}
 
 
 
cs

7. 플래시 메시지

패스포트에서는 플래시 메시지를 이용하여 로그인이 성공 하면, 성공 메시지를 출력 하거나 실패 하면 실패 메시지를 1회성으로 출력 할수 있습니다. 내부적으로 connect-flash에 의존 하고 있어서 해당 하는 기능을 사용하기 위해서는 connect-flash를 설치 해야 합니다. 

 

플래시 설치 

 npm install -s connect-flash

 

플래시 예제코드 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//Hoons Blog---https://rain2002kr.tistory.com------------------------------------------------------------------코드///
 
//플래시 테스트 코드 
app.use(flash());
app.get('/flash', function(req,res){
    req.flash('into''Flash is back!'); //세션안에 저장합니다. 
    res.send('flash');
})
 
router.get('/flash-display', function(req,res){
    var fmsg = req.flash(); //세션안에 들어있는 값을 잘라내기해서 가져옵니다. 
    console.log(fmsg)
    res.send('flash messgae: ',fmsg);
})
 
 
cs

플래시의 특징은 req.flash('안에 인자값') 있는 경우는 추가하고, req.flash() 이렇게 호출 하면 그안에 내용을 잘라내기 해서 바로 리턴값으로 가져와서 사용합니다. 패스포트에서는 이러한 특성을 이용하여, 로그인 성공, 실패 했을때 1회용 메시지를 출력 할수 있도록 설계 되어있습니다. 

 

패스포트 플래시 적용 파트 

 1. passport.authenticate 에 failureFlash 를 true와 sucessFlash 에 값을 설정 합니다. 

 2. passport.LocalStrategy 에서 message를 세팅 합니다. 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
//Hoons Blog---https://rain2002kr.tistory.com------------------------------------------------------------------코드///
 
//LOGIN PROCESS with Passport Method is POST 
router.post('/login_process',
passport.authenticate('local', { 
    successRedirect: '/',                      
    failureRedirect: '/auth/login',   
    failureFlash: true,             //이 값을 true 로 설정 해줘야 합니다. 
    successFlash: 'logined!'        //성공 했을때 플래시 메시지 설정입니다. 
}));
 
    return router;
}
 
// 패스포트 아이디와 패스워드를 검사하는 로직중 done 함수로 message 값을 주는 부분이 fail 했을때 리턴 값입니다. 
//패스포트 사용 
passport.use(new LocalStrategy(
    //사용자가 필드를 변경시키고 싶으면 아래처럼 추가 합니다. 
    {
        usernameField: 'email',
        passwordField: 'password'
    },
    function(username, password, done) {
        console.log('LocalStrategy ' + username, password)
        if(username === authDate.email){
            console.log('1');
            if(password === authDate.password){
                console.log('2');
                return done(null, authDate); //아이디와 비번이 일치할때, done 함수로 유저데이터를 넣어주면 session에 등록됩니다. 
            } else {
                console.log('3');
                return done(nullfalse, { message: 'Incorrect password.' });      
            }
        } else {
            console.log('4');
            return done(nullfalse, { message: 'Incorrect username.' });
        }
    }
  ));
 
 
 
cs

3. 등록된 플래시 메시지 사용하기 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
//Hoons Blog---https://rain2002kr.tistory.com------------------------------------------------------------------코드///
 
//WEB PAGE Content load 
router.get('/', function (request, response) {
    //패스포트를 이용해서 로그인에 성공하면, requset.user 로 값이 들어옵니다. 
    console.log('root page: ', request.user);
    var fmsg = request.flash(); //플래시 샘플코드에서 처럼 다음과 같이 호출하면 메시지를 잘라내기해서 리턴 합니다. 
     console.log('flash',fmsg);
     var feedback =''
     if(fmsg.success){
        feedback = fmsg.success[0//성공 했을때 메시지 가져오는 방법 입니다.   
     }
     console.log('feedback',feedback);
 
//코드 생략
 
module.exports= function(passport){
//LOGIN 
router.get('/login', function(request, response){
     //플래시 메시지 request.flash 로 들어옵니다. 
     var fmsg = request.flash(); //플래시 샘플코드에서 처럼 다음과 같이 호출하면 메시지를 잘라내기해서 리턴 합니다. 
     console.log('flash',fmsg);
     var feedback =''
     if(fmsg.error){
        feedback = fmsg.error[0//실패 했을때 메시지 가져오는 방법 입니다.   
     }
     
 
 
 
cs

8. 로그아웃 

패스포트를 이용하여 로그아웃 하는 방법은 다음과 같습니다. 추가적으로 세션이 삭제된 이후에 리다이렉션 코드를 넣어 주는게 좋습니다. 이 리다이렉션을 바로 홈으로 보내면 세션이 삭제되지 않은 상태에서 이후에 삭제되는 오류가 발생 할수 있습니다. 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//Hoons Blog---https://rain2002kr.tistory.com------------------------------------------------------------------코드///
 
//LOGOUT 
router.get('/logout', function(request, response){
    //패스포트 로그아웃 
    request.logout();
    //세션 현재상태 저장후, 콜백 오면 리다이렉션 
    request.session.save(function(err){
        response.redirect('/');
    })
});
 
 
 
 
cs

 


전체코드 공유

 

 

rain2002kr/Life_Express_PassportJS

생활코딩 패스포트 예제코드 입니다. . Contribute to rain2002kr/Life_Express_PassportJS development by creating an account on GitHub.

github.com

 

 

 

 

반응형