티스토리 뷰

이 페이지에서는 passport.js 패키지를 이용하여 로그인을 구현하는 방법을 설명하고 있다.



# 패키지 설치

우선 아래의 코드를 이용해서 패키지를 설치한다.

npm install passport passport-local express-session

passport passport-local은 로그인을 구현할 때, express-sesion은 로그인 후 세션에 유저정보를 입력할 때 사용될 것이다.



# 화면구현 Code

api를 호출해서 화면에 출력하는 과정에 대해서는 지난 포스트에서 설명했다.

참고) https://kkumalog.tistory.com/49

이번에는 폼을 출력하고 폼에 입력한 데이터들을 post로 넘겨주는 과정을 설명하려한다.

form action="/login" method="post"를 해석하면, /login 주소로 form data를 post방식으로 넘겨준다는 뜻이다.


1) api/test.js

function  templateHTML() {
return  `
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<form action=“/login” method=“post”>
<div>
<label>UserId:</label>
<input type=“text” name=“username”/><br/>
</div>
<div>
<label>Password:</label>
<input type=“password” name=“password”/>
</div>
<div>
<button type=“submit”>Submit</button>
</div>
</form>
</body>
</html>
`;
}
exports.loginForm =   function  getLoginForm(req, res, next) {
res.send(templateHTML());
}


2) router/test.js

const  router = require(‘express’).Router();
const  test = require(‘../api/test’);

router.get(‘/‘, test.loginForm);

module.exports = router;


3) 로그인 화면 실행

https://localhost:3000/test



# 로그인구현 Code

로그인폼에서 받아온 username, password를 passport.js를 이용해서 로그인 인증을 구현한다.

코드 설명에 앞서, 흐름을 간단하게 설명하면 다음과 같다.

- admin테이블에 있는 유저들과 입력된 값을 비교한다

- username이 존재한다면, 암호화되어있는 유저 비밀번호를 해독(복호화, decryption)하여 비교한다

- 로그인 후에는 세션에 유저정보를 저장한다


1) database/dynamodb/admin.js

const  router = require(‘express’).Router();
const  test = require(‘../api/test’);

router.get(‘/‘, test.loginForm);

module.exports = router;


2) passport.js

const passport = require(‘passport’),
LocalStrategy = require(‘passport-local’).Strategy;
const bcrypt = require(‘bcrypt-nodejs’);

const adminDB = require(‘../database/dynamodb/admin’);

exports.setup = async function() {
passport.use(‘login’, new LocalStrategy({
usernameField: ‘username’,
passwordField: ‘password’,
session: true,
passReqToCallback: true,
},
async function (req, username, password, done) {
try {
const users = await adminDB.getAdmin();
for ( const user  of users) {
if (username === user.id) {
if (bcrypt.compareSync(password, user.pw)) {
return done(null, user);
}
}
}
return done(null, false, {message: ‘Not found user’})
} catch (err) {
return Promise.reject(err);
}
}
));

passport.serializeUser(function (user, done) {
done(null, user);
});

passport.deserializeUser(function (user, done) {
done(null, user);
});
}

serializeUser는 로그인 성공 시 실행되는  done(null, user)에서 user 객체를 받아 req.session.passport.user 세션에 저장한다. 

저장된 세션은 페이지 이동 시에도 로그인 정보가 유지된다.


deserializeUser는 서버로 들어오는 요청마다 세션 정보를 실제 DB의 데이터와 비교한다. 해당하는 유저 정보가 있으면 done의 두 번째 인자를 req.user에 저장하고, 요청을 처리할 때 유저의 정보를 req.user를 통해서 넘겨준다.


passport를 동작시키게하기위해서는 이 두 메서드는 꼭 필요하다


3) api/login.js

const passport = require(‘passport’);

require(‘../libs/passport’).setup();

exports.getLogin = async (req, res, next) => {
let isValid = true;
if (!req.body.username){
isValid = false;
}
if (!req.body.password){
isValid = false;
}
try {
if (isValid) {
passport.authenticate(‘login’, {
successRedirect: ‘/login/success’,
failureRedirect: ‘/login/failure’
})(req, res, next);
};

catch (errors) {
return next(errors);
}
};


exports.loginSuccess = async (req, res, next) => {
res.redirect(“success”);

}


exports.loginFailure = async (req, res, next) => {
res.send(“fail”);
}


4) router/login.js

const router = require(‘express’).Router();
const login = require(‘../api/login’);

router.post(‘/‘, login.getLogin);
router.get(‘/success’, login.loginSuccess);
router.get(‘/failure’, login.loginFailure);

module.exports = router;


5) app.js

const express = require(‘express’);
const app =  express();
const bodyParser = require(‘body-parser’);
const passport = require(‘passport’);
const session = require(‘express-session’);

const main = require(‘./router/main’);
const admin = require(‘./router/admin’);
const test = require(‘./router/test’);
const login = require(‘./router/login’);

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended:  false }));

app.use(session({
secret: ‘!@#’,
resave:  false ,
saveUninitialized:  true 
}));

app.use(passport.initialize());
app.use(passport.session());

app.use('/', main);
app.use('/admin', admin);
app.use('/test', test);
app.use('/login', login);

app.listen(3000, function() {
console.log(‘Example app listening on port 3000!’);
});



# 로그인 코드 실행

https://localhost:3000/login/success

https://localhost:3000/login/failure


댓글
최근에 올라온 글
«   2024/07   »
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
Total
Today
Yesterday