Passportjs 1 : intro
PassportJS 모듈 : 인증(Authentication)을 쉽게 구현할 수 있도록 도와주는 모듈
오늘 날은 인증의 방법이 다양 - 이미 다른 서비스에 가입된 정보를 이용해서 인증하는 방식이 많이 사용됨
-> Federation Authentication : ex) Login with Google
-> 이렇게 다양한 인증 기관을 사용할 때 PassportJS 모듈을 사용하면 구현의 복잡도가 낮아짐.
Passportjs 2 : configure
https://www.passportjs.org/docs/
Facebook이나 Google같은 다른 기관에서 제공하는 인증을 사용하려면 Strategies에서 해당 기관에 맞는 모듈을 다운받아야 한다. passport-local은 자체적으로 비밀번호와 아이디를 통해 인증을 진행할 경우 사용한다.
npm install --save passport passport-local
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
...
app.use(passport.initialize());
app.use(passport.session()); //session을 먼저 setting한 후에 추가해야함.
Passportjs 3 : route
passport.use(new LocalStrategy( //사용 전 전략을 설정해주어야 함.
function(username, password, done){
var uname = username;
var pwd = password;
for (var i=0; i<users.length; i++){
var user = users[i];
if (uname === user.username) {
return hasher({password: pwd, salt: user.salt},
function(err, pass, salt, hash){
if (hash === user.password){
done(null, user); //login 성공
} else{
done(null, false); //login 실패
}
});
}
}
done(null, false); //첫번째 인자는 에러처리에 사용. 세번째 인자로 메시지를 넣고, failureFlash에 true를 했다면 보여줌.
}
))
app.post('/auth/login',
passport.authenticate('local', {
successRedirect: '/welcome', //로그인 성공하면 해당 페이지로 redirect
failureRedirect: '/auth/login', //로그인 실패시 redirect
failureFlash: false //최신 docs에는 포함되어있지 않음. 중요도에비해 복잡도가 높다고 함. 사용자에게 인증 실패시 메세지를 보여줌.
}));
passport가 미들웨어로 기능한다.
Passportjs 4 : serialize
https://www.passportjs.org/tutorials/password/session/
공식문서를 참고하니, 강의에서 말한 실습 예제와 코드가 조금 달랐다. done -> cb 로 받아오는 것 같고, passport.serializeUser 안에서 콜백함수를 실행하기 전에 process.nextTick이라는 콜백함수를 먼저 실행하고 그 안에서 강의에서 말하는 done(cb) 콜백함수를 실행하는 것 같다.
nextTick()은 사용자의 동기코드 이후, 이벤트루프가 진행되기 이전 의 시간을 목적으로 한다.. 고 하는데, 아직 잘 이해가 되지 않지만 아무튼 그렇다고 한다. 공식 문서에 저렇게 되어 있으니 이렇게 하는게 더 안정성이 좋으니까 그런거겠지..?
cb(done) 함수의 두번째 인자로 user를 식별할 수 있는 식별자를 주어야 하는데, 예제 코드에서는 id값을 따로 주지 않고 그냥 username을 사용했다.
passport.serializeUser(function(user, cb) { //Strategy 성공 시 호출됨
console.log('serializerUser', user);
process.nextTick(function() {
cb(null, user.username); // username값이 세션에 등록되는 것. req.session.passport.user
//user.username이 deserializeUser의 첫번째 매개변수로 이동
});
});
passport.deserializeUser(function(id, cb) {
console.log('deserializeUser', id);
process.nextTick(function(){
for (var i=0; i<users.length; i++){
var user = users[i];
if (user.username === id){
return cb(null, user); // req.user 등록됨.
}
}
})
}
);
💣 처음엔 어떻게 해도 deserializeUser가 실행이 안되길래, 생활코딩 홈페이지를 들어가보니 나와 같은 에러를 겪은 사람이 많았다. 문제는 app.use(session) 에서 store: new FileStore(); 를 없애주면 해결되었다. session에 저장이 안돼서 생긴 문제였다.
app.get('/welcome', function(req, res){
if (req.user && req.user.displayName){ //변경된 부분.
res.send(`
<h1>Hello, ${req.user.displayName} </h1>
<a href="/auth/logout">Logout</a>
`);
} else{
res.send(`
<h1>Welcome</h1>
<a href="/auth/login">Login</a>
<p><a href="/auth/register">Register</a>
`);
}
});
welcome 페이지에서 로그인 후 displayName이 출력되게 하려면 req.session.displayName 부분을 req.user.displayName으로 변경해야 한다.
Passportjs 5 : logout
app.get('/auth/logout', function(req, res){
req.logout();
req.session.save(function(){
res.redirect('/welcome'); // session 정보 저장이 끝난 후에 redirect 실행
});
});
passportjs 에서 제공하는 logout 함수를 이용해서 logout 기능을 간단하게 구현할 수 있다. 안정성을 위해 save 함수는 그대로 두는 걸 추천한다.
app.post('/auth/register', function(req, res){
hasher({password:req.body.password}, function(err, pass, salt, hash){
var user = {
username: req.body.username,
password: hash,
salt: salt,
displayName: req.body.displayName
};
users.push(user);
req.login(user, function(err){ // login function
req.session.save(function(){
res.redirect('/welcome');
});
})
})
})
register페이지에서 바로 로그인해서 welcome 페이지로 넘어가는 기능을 구현할 때, passportjs에서 제공하는 login 함수를 이용할 수 있다.
'스터디📖 > Node.js' 카테고리의 다른 글
[nodejs] Node.Js 활용하기 - 섹션 7. Mysql 버전으로 로그인 인증 구현하기 (0) | 2022.02.15 |
---|---|
[nodejs] Node.Js 활용하기 - 섹션 5. 타사인증 (Federation authentication) (0) | 2022.02.14 |
[nodejs] Node.Js 활용하기 - 섹션 3. 비밀번호 보안 (Security Password) (0) | 2022.02.12 |
[nodejs] Node.Js 활용하기 - 섹션 2. Session (0) | 2022.02.12 |
[nodejs]Node.Js 활용하기 - 섹션 1. cookie (0) | 2022.02.11 |