티스토리 뷰

안녕하세요 탐구소년입니다. 

 

NodeJS로 서버를 제작할 때는 유용한 패키지를 많이 사용할수록 간결하게 필요한 기능을 구현할 수가 있습니다. 다양한 패키지 중에서도 passport라는 이름의 패키지는 사용자 인증과 관련된 기능을 제공하는 유용한 패키지인데, 일 때문에 passport의 간단한 예제가 필요해져서, 필요한 최소한의 기능만을 구현한 예제를 만들어봤습니다. 혹시나 passport 예제가 필요하신 분들이 참고하시면 좋을 것 같아서 블로그에 올려봅니다. 여기에서는 일단 passport가 대략 어떤 것인지에 대해서, 그리고 node 앱이 대강 어떻게 구성되는지에 대해서는 어느 정도 알고 계신 분들이 본다고 가정하고 코드 위주로만 올리도록 하겠습니다.

 

먼저 프로젝트 폴더의 구조는 다음과 같습니다. 

뷰는 ejs를 사용했고, 로그인 화면과 로그인 성공/실패시 화면을 각각 만들었습니다. 그리고 동작 구현에 필요한 최소한의 기능만을 자바스크립트로 구현해봤는데, 비밀번호 암호화라던지 보안 관련 내용은 전혀 포함하지 않았습니다. 그저 정해져있는 아이디와 비밀번호가 통과가 되는지 되지 않는지만을 구현했고, passport의 사용법만을 간단히 구현해 본 것입니다.

 

Node 프로젝트인 만큼, 가장 먼저 package.json부터 보도록 하겠습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
{
  "name""passport-exam",
  "version""1.0.0",
  "description""",
  "main""index.js",
  "scripts": {
    "test""echo \"Error: no test specified\" && exit 1",
    "start""node index.js"
  },
  "author""",
  "license""ISC",
  "dependencies": {
    "connect-flash""^0.1.1",
    "ejs""^3.1.5",
    "express""^4.17.1",
    "express-session""^1.17.1",
    "passport""^0.4.1",
    "passport-local""^1.0.0"
  },
  "devDependencies": {
    "nodemon""^2.0.4"
  }
}
 

설치된 패키지를 보면, passport와 passport-local이 있는 것을 확인할 수 있습니다. passport는 로그인/로그아웃/회원가입 인증을 도와주는 미들웨어로써, 대부분의 express 앱에서 인증 용으로 사용하는 인기 패키지입니다. 또한 flash는 서버쪽 passport 미들웨어에서 메시지를 전송할 때 사용합니다.

 

 

이번에는 뷰 부분의 코드들부터 보겠습니다. 설명이 필요없는 코드입니다. 

 

index.ejs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title><%= title %></title>
</head>
<body>
  <h1>로그인하기</h1>
  <form method="POST" action="/">
    <label for="userId">아이디</label>
    <input type="text" id="userId" name="userId"><br>
    <label for="password">비밀번호</label>
    <input type="password" id="password" name="password"><br>
    <button>로그인</button>
  </form>
</body>
</html>

 

loginSuccess.ejs

1
2
3
4
5
6
7
8
9
10
11
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>로그인 성공</title>
</head>
<body>
  <h1>로그인 성공!</h1>
</body>
</html>

 

loginFail.ejs

1
2
3
4
5
6
7
8
9
10
11
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>로그인 실패</title>
</head>
<body>
  <h1>로그인 실패!</h1>
</body>
</html>

 

 

다음은 프로그램의 실질적 실행부(main)라고 할 수 있는 index.js를 보겠습니다.

 

index.js

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
const express = require('express')
const app = express()
const route = require('./router.js')
const bodyParser = require('body-parser')
 
const expressSession = require('express-session');
const passport = require('./passport.js')
const flash = require('connect-flash')
 
app.set('views', __dirname + '/public')
app.set('view engine''ejs')
 
app.use(bodyParser.urlencoded({extended:false}))
app.use(bodyParser.json())
 
app.use(passport.initialize())
app.use(passport.session())
app.use(flash())
app.use(expressSession({
    secret: 'my Key',
    resave: true,
    saveUninitialized:true
}))
 
app.use('/', route)
 
app.listen(4003, () => {
    console.log("4003 port is on!")
})

 

4003포트를 서버 포트로 사용하는 앱을 만들었습니다. 뷰 엔진은 ejs이고, 폼으로부터 전달되는 데이터를 처리하기 때문에 body-parser 패키지도 적용했습니다. passport 관련 기능은 따로 파일을 만들어 정의한 다음 import하고 있습니다.

 

다음 코드는 passport 관련 파일입니다.

 

passport.js

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
const passport = require('passport')
const LocalStrategy = require('passport-local').Strategy;
 
passport.use('local-login'new LocalStrategy({
    usernameField: 'userId',
    passwordField: 'password',
    passReqToCallback: true
}, (req, userId, password, done)=>{
    console.log('passport의 local-login : ', userId, password )
 
    if(userId != "kang" || password != "12345"){
        console.log('비밀번호 불일치!')
        return done(nullfalse, req.flash('loginMessage''비밀번호 불일치!'))
    }
 
    console.log('비밀번호 일치!')
    return done(null, {
        userId : userId,
        password: password
    })
 
}))
 
passport.serializeUser(function(user, done) {
    console.log('serializeUser() 호출됨.');
    console.log(user);
    
    done(null, user); 
});
 
passport.deserializeUser(function(user, done) {
    console.log('deserializeUser() 호출됨.');
    console.log(user);
    
    done(null, user);  
});
 
 
module.exports = passport

아이디가 "kang"으로, 비밀번호가 "12345"로 정해져 있는 상태에서 로그인을 한다고 가정한 코드입니다. 그러나 저 부분은 얼마든지 바꿔줄 수 있습니다. 데이터베이스로부터 해당 아이디의 비밀번호를 읽어와 일치 여부를 판단하는 방식이 일반적일 것입니다. 

 

마지막으로 router.js 를 보겠습니다.

 

router.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
const express = require('express')
const router = express.Router()
const passport = require('./passport.js')
 
router.get('/', (req, res) => {
    res.render('index', {title: "인덱스"})
})
 
router.post('/', passport.authenticate('local-login', {
    successRedirect : '/loginSuccess'
    failureRedirect : '/loginFail'
    failureFlash : true 
}))
 
router.get('/loginSuccess', (req, res) => {
    res.render('loginSuccess')
})
router.get('/loginFail', (req, res) => {
    res.render('loginFail')
})
 
 
module.exports = router

 

 

여기까지 코드는 모두 완성입니다. 그럼 실행 예를 보여드리면서 마무리하겠습니다.

 

먼저, 올바르게 비밀번호를 작성했을 때입니다.

 

로그인에 성공합니다. 

 

이번엔 비밀번호를 일부러 틀리게 작성해보았습니다. 

 

로그인에 실패합니다. 

 

여기까지만 놓고 보면, passport를 사용한 것과 사용하지 않은 것에는 별 차이가 없어 보이기도 합니다. 오히려 코드만 더 복잡해진 것으로 보이기도 합니다. 그러나 세션에 대한 처리, 비밀번호 암호화에 대한 처리 등을 추가하다보면 passport가 무척 유용하다는 것을 알게 되실 겁니다. 

 

 

댓글
공지사항