Passportjs 로그아웃 구현
메뉴얼의 Login 과 Logout을 읽어보면
passport.authenticate() 미들웨어는 req.login()을 자동으로 호출한다고 써있고, req.login()함수는 signup(회원가입)할때 주요하게 사용된다고 메뉴얼에 써있다. 그리고 req.login함수가 끝나면 req.user 객체가 자동으로 생성됨을 알 수 있다.
윗 설명을 읽어보면 req.logout()이라는 메소드를 호출하면 req.user에 들어있는 로그인 세션이 삭제된다는 뜻이다.
즉 이 메소드는 로그아웃할 때 호출해야 한다.
소스가 수정된 부분은 노란색으로 표시함.
var express = require('express');
var session = require('express-session');//세션 사용을 위한 모듈
var bodyParser = require('body-parser');//POST 방식 전송을 위해서 필요함
var app = express();
var FileStore = require('session-file-store')(session);//session 파일 스토어를 위해 사용
var bkfd2Password = require("pbkdf2-password");//pbkdf2-password 모듈 사용
var hasher = bkfd2Password();
var passport = require('passport');//passport 모듈 사용
var LocalStrategy = require('passport-local').Strategy;//passport 모듈 사용
app.use(bodyParser.urlencoded({extended: false}));//미들웨어 등록부분
//resave 세션아이디를 접속할때마다 발급하지 않는다
app.use(session({
secret: '12312dajfj23rj2po4$#%@#',
resave: false,
saveUninitialized: true,
store:new FileStore()//sessions라는 디렉토리가 생김
}));
app.use(passport.initialize());//passport 초기화
app.use(passport.session());//passport 인증 작업시 필요 이것은 세션을 사용하기 위한 윗 app.use(session)뒤에 써야한다
app.get('/auth/logout', function(req, res){
req.logout();//passportjs에 있는 기능
req.session.save(function(){//세션작업이 끝난상태에서 안전하게 welcome페이지로 이동
res.redirect('/welcome');
});
});
app.get('/welcome', function(req, res){
//console.log(req.user);
//passportjs의 세션을 이용하는게 바람직함
if(req.user && req.user.displayName){//req객체에 user가 생성되었고 값이 있으면 로그인 성공
res.send(`
<h1>Hello, ${req.user.displayName}</h1>
<a href="/auth/logout">logout</a>
`);
}else{//값이 없으면 로그인에 실패 혹은 로그인 안한사람
res.send(`
<h1>Welcome</h1>
<ul>
<li><a href="/auth/login">Login</a></li>
<li><a href="/auth/register">Register</a></li>
</ul>
`);
}
});
var users = [
{
username:'egoing',
password:'bXHtzdi7m+jclUkfYdqgGsm5nYpBBYrqUFjkP+wHFF/j+zFipSf2N8GZJ7eD0yp9T9ovLbnCjjtS/upvcIL8Tw2ffG0G6vnk1vQfG4qMmSyXM4Aug8xgzJxGalSCnbkMVQR5A8r22kKoeTQIjkQtMFisPwZQZSuknrreGuq9am4=',
salt:'rWfFWL8EZGoKGGbzryiu1ZJfkfhvBo0XMinpFrJLTy43EmOV2g9LXIL6385l5FerQAlVK1jXYNmFryKHREPXxQ==',
displayName:'egoing'
},
];
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,//hash로 대체함
salt:salt,//만든 salt값도 같이 저장함
displayName:req.body.displayName
};
users.push(user);//입력한 값을 users배열 맨뒤에 추가함
req.login(user, function(err){//회원가입이 되고 바로 동시에 로그인 하기 위함
req.session.displayName = req.body.displayName;
req.session.save(function(){
res.redirect('/welcome');
});
});
});
});
app.get('/auth/register', function(req, res){
var output = `
<h1>Register</h1>
<form action="/auth/register" method="post">
<p>
<input type="text" name="username" placeholder="username">
</p>
<p>
<input type="password" name="password" placeholder="password">
</p>
<p>
<input type="text" name="displayName" placeholder="displayName">
</p>
<p>
<input type="submit">
</p>
</form>
`;
res.send(output);
});
//done(null, user)가 호출되면 이게 호출됨 여기의 user는 아래 콜백의 user임
passport.serializeUser(function(user, done) {
console.log('serializeUser', user);
done(null, user.username);//username 또는 고유의 id값을 넘겨줘야함 유저를 찾는데 사용함 이 데이터는 세션에 저장됨
});
//serializeUser실행 후 다음 유저는 deserializeUser메소드로 옴
//즉 id는 user.username임
passport.deserializeUser(function(id, done) {
console.log('deserializeUser1', id);
for(var i=0; i < users.length; i++){
var user = users[i];
if(user.username === id){
done(null, user);//여기가 끝나면 req.user에 user객체가 저장된다.
//console.log('deserializeUser2', user);
}
}
});
//미들웨어부분
passport.use(new LocalStrategy(
function(username, password, done){//여기서 실제 사용자가 맞는지 인증하는 부분을 수행
var uname = username;//POST방식으로 보낸 값을 가져옴
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){//salt는 이미 저장된 salt값을 넘겨줌
if(hash === user.password){//저장된 해쉬값과 만든 해쉬값이 같으면 인증 성공
console.log('localstrategy', user);
done(null, user);//로그인 성공을 의미 serializeUser 호출 윗 파라미터의 done이 아니다
}else{
done(null, false);//로그인 실패를 의미 message항목은 failureFlash가 true일때만 씀
}
});
}
}//for문종료
done(null, false);
}
));
//전송된 데이터는 passport.authenticate라는 미들웨어로 가게함
//성공시 /welcome으로
//실패시 /auth/login으로 감
//로그인 실패시 사용자에게 인증에 실패했다고 정보를 알려주는 것이 failureFlash: true
// 'local전략을 쓰라는뜻 만약 페이스북이면 'facebook'이 될 것임
//local 전략이 실행되면 function(username, password, done) 콜백이 실행됨
app.post('/auth/login',
passport.authenticate('local', {
successRedirect: '/welcome',
failureRedirect: '/auth/login',
failureFlash: false })
);
app.get('/auth/login', function(req, res){
var output = `
<h1>Login</h1>
<form action="/auth/login" method="post">
<p>
<input type="text" name="username" placeholder="username">
</p>
<p>
<input type="password" name="password" placeholder="password">
</p>
<p>
<input type="submit">
</p>
</form>
`;
res.send(output);
});
app.get('/count', function(req, res){
if(req.session.count){//값이 있을때
req.session.count++;
}else{//처음 접속했을때 즉 값이 없을 때
req.session.count = 1;//세션을 만듬
}
res.send('count : ' + req.session.count);
});
app.listen(3003, function(){
console.log('Connected 3003 port!!!');
});
실행화면
여기서 로그인 클릭
ID: egoing PW:111111
로그인 후 logout을 누르면 다시 logout 페이지로 감을 알 수 있다.
그 다음 register클릭 후 사용자 등록을 하면
등록과 동시에 바로 로그인이 된다.
Passport.js 예제 정리
1. app.post(passport.authentication) 호출
2. passport.use(new LocalStrategy) 호출
3. done 함수 호출 done(null, user) -> 로그인 성공 -> /welcome 페이지로 감
done(null, false) -> 로그인 실패 -> /auth/login 페이지로 감
4. 로그인 성공시 serializeUser 호출 3번의 done(null, user)에서 user값이 파라미터로 옴
serializeUser(function(user, done){
done(null, user.username) -> 식별자(ID)를 넘겨줘야함.(이 값이 세션에 설정됨)
}
5. 그 다음페이지 deserializeUser(function(id, done)) 호출
6. id 값에 해당되는 사용자 정보를 DB에서 찾고 done(null, user)를 호출
7. passportjs에 의해서 req.user객체가 자동으로 추가됨.
8. /welcome으로 이동 시 이 값으로 로그인 성공/실패여부를 알 수 있게됨.
출처 : https://opentutorials.org/course/2136
'프로그래밍 > Node.js' 카테고리의 다른 글
Node.js 생활코딩 정리 – MYSQL을 이용한 회원가입(Register) (0) | 2016.12.08 |
---|---|
Node.js 생활코딩 정리 – 인증 기능을 MYSQL을 이용해서 구현하기 (0) | 2016.12.07 |
Node.js 생활코딩 정리 – facebook 인증 세부 권한 설정 (0) | 2016.12.05 |
Node.js 생활코딩 정리 – Federation Authentication (타사 인증) 페이스북으로 인증하기 (0) | 2016.12.05 |
Node.js 생활코딩 정리 – Passportjs 인증 모듈 사용하기 (0) | 2016.12.04 |
Node.js 생활코딩 정리 – Password Key Stretching 기법(PBKDF2 도입) (0) | 2016.12.04 |
Node.js 생활코딩 정리 – Password 암호화 방법 (0) | 2016.12.04 |
Node.js 생활코딩 정리 – 인증 기능 추가하기 (0) | 2016.12.03 |