github 주소 : https://github.com/GoF9490/board
이번 로그인 기능에서 언급할 코드들은 전에 만든 로그인 기능을 express와 passport에 맞춰서 수정, html 템플릿과 css는 조금만 변경해서 재활용했다.
// 로그인
router.get('/login', (req, res)=>{
let fmsg = req.flash(); // connect-flash 미들웨어를 사용
let feedback = (fmsg.message) ? fmsg.message : '';
return res.send(template.login(feedback));
});
router.post('/login_process', (req, res, next)=>{
passport.authenticate('local', (err, user, info)=>{
if (err) return next(err);
if (!user){
req.flash('message', info.message);
return req.session.save(()=>{
return res.redirect('/auth/login');
});
}
req.logIn(user, (err)=>{ // passport 미들웨어를 사용해서 로그인하는 방식
if (err) return next(err);
return req.session.save(()=>{
return res.redirect('/');
});
});
})(req, res, next);
});
해당 코드의 라우터는 /auth 주소로 통하고있다.
즉 /auth/login 주소로 이동을 하면, 로그인 html 템플릿을 뱉는다.
이후 로그인 창에서 작성된 이메일, 비밀번호를 post방식으로 받아온 후 passport.authenticate 커스텀함수를 통해 로그인이 성공했다면 메인페이지로, 실패했다면 flash메세지와 함께 로그인창으로 리다이렉트된다.
전체적으로 이전의 게시물들을에서 언급되었던 코드들이니 여기까지만 설명하겠다.
// 회원가입
router.get('/register', (req, res)=>{
let fmsg = req.flash();
let feedback = (fmsg.message) ? fmsg.message : '';
return res.send(template.register(feedback));
});
router.post('/register_process', (req, res, next)=>{
let body = req.body;
if (!body.email.includes('@')){
req.flash('message', '이메일 형식을 확인해주세요.');
return req.session.save(()=>{
res.redirect('/auth/register');
});
}
if (body.password.length < 8){
req.flash('message', '비밀번호는 8자리 이상이여야 합니다.');
return req.session.save(()=>{
res.redirect('/auth/register');
});
}
if (body.password !== body.password2){
req.flash('message', '비밀번호가 일치하지 않습니다.');
return req.session.save(()=>{
res.redirect('/auth/register');
});
}
if (body.nickname.length < 3){
req.flash('message', '닉네임은 3글자 이상이여야 합니다.');
return req.session.save(()=>{
res.redirect('/auth/register');
});
}
if (!body.answer){
req.flash('message', '질문에 대한 답변을 입력해주세요.');
return req.session.save(()=>{
res.redirect('/auth/register');
});
}
bcrypt.hash(body.password, 10, (err, hash)=>{
if (err) return next(err);
db.query(`INSERT INTO users
(email, password, nickname, question, answer, day)
VALUES (?, ?, ?, ?, ?, NOW())`,
[body.email, hash, body.nickname, body.question, body.answer],
(err1, result)=>{
if (err1) return next(err1);
db.query(`SELECT * FROM users WHERE email=?`,[body.email],(err2, result2)=>{
if (err2) return next(err2);
return req.login(result2[0], (err3)=>{
if (err3) return next(err3);
return res.redirect('/');
});
});
return;
});
});
});
flash 변수를 html 템플릿으로 주는 방식은 로그인때랑 같다.
프로세스 에서는 bodyparser 미들웨어를 통해 파싱된 body에 담겨있는, 입력된 변수들을 통해 여러 조건을 if문으로 대조 후 조건이 맞지않다면 회원가입 페이지로 flash 메세지와 함께 리다이렉트 시킨다. (여기서 조금 불만인게, 단순 리다이렉트 시키면 작성되었던 정보들이 날라가버린다. history를 통한 뒤로가기 같은걸로 바꿔주면 좋을것같다.)
이후 조건이 전부 통과되었으면, bcrypt 미들웨어를 통해 패스워드를 암호화, 데이터베이스의 users 테이블에 저장 후, 해당 값을 다시 가져와 req.login 함수를 통해 로그인을 성공시킨 후 메인페이지로 리다이렉트 시킨다.
// 로그아웃
router.get('/logout_process', (req, res)=>{
return req.logout(()=>{
req.session.save(()=>{
res.redirect('/');
});
});
});
req.logout 함수를 사용, 이후 세션이 안전하게 변경되도록 session.save 함수로 콜백, 메인페이지로 리다이렉트 시킨다.
별거없이 간단하다.
// 비밀번호 재설정
router.get('/findPw', (req, res)=>{
let fmsg = req.flash();
let feedback = (fmsg.message) ? fmsg.message : '';
return res.send(template.findPw(feedback));
});
router.post('/findPw_process', (req, res, next)=>{
let body = req.body;
if (!body.email.includes('@')){
req.flash('message', '이메일 형식을 확인해주세요.');
return req.session.save(()=>{
res.redirect('/auth/findPw');
});
}
if (body.password.length < 8){
req.flash('message', '비밀번호는 8자리 이상이여야 합니다.');
return req.session.save(()=>{
res.redirect('/auth/findPw');
});
}
if (body.password !== body.password2){
req.flash('message', '비밀번호가 일치하지 않습니다.');
return req.session.save(()=>{
res.redirect('/auth/findPw');
});
}
if (!body.answer){
req.flash('message', '질문에 대한 답변을 입력해주세요.');
return req.session.save(()=>{
res.redirect('/auth/findPw');
});
}
db.query(`SELECT question, answer FROM users WHERE email=?`,[body.email],(err, results)=>{
if (err) return next(err);
if (!results[0]){
req.flash('message', '일치하는 이메일이 존재하지 않습니다.');
return req.session.save(()=>{
res.redirect('/auth/findPw');
});
}
if (results[0].question != body.question | results[0].answer !== body.answer){
req.flash('message', '질문과 답변이 올바르지 않습니다.');
return req.session.save(()=>{
res.redirect('/auth/findPw');
});
}
bcrypt.hash(body.password, 10, (err, hash)=>{
if (err) return next(err);
db.query(`UPDATE users SET password=? WHERE email=?`,[hash, body.email], (err1, results2)=>{
if (err1) return next(err1);
return res.redirect('/auth/login');
});
});
});
});
body값을 가져와 조건과 비교, 안될시 패스워드 재설정 페이지로 리다이렉트.
모든 조건을 통과시, users 테이블에서 입력된 email과 대조되는 데이터의 질문과 답변 값을 가져와 다시한번 body값과 대조, 이 마저도 통과하면 update문을 사용해 새로입력된 패스워드를 bcrypt를 통해 암호화 시킨 후 저장, 이후 로그인 페이지로 리다이렉트.
사실 전 게시물에서는 단순히 패스워드를 뱉어내는 기능이였으나, 패스워드를 암호화해서 저장함으로서 db의 관리자도 원래의 패스워드를 알아내는것은 불가능, 패스워드를 재설정하는 기능으로 바꾸었다.
'프로젝트' 카테고리의 다른 글
Node.js - 게시판 ( 게시물 및 댓글 작성 / 삭제 ) (0) | 2022.09.07 |
---|---|
Node.js - 게시판 ( 작성 / 수정 / 삭제 ) (0) | 2022.09.05 |
Node.js - 게시판 ( 메인페이지 ) (0) | 2022.09.04 |
Node.js - Express passport.authenticate 커스텀 함수 - flash 가 session 에 저장이 안될때. (0) | 2022.08.28 |
Node.js - 로그인 기능 구현 (0) | 2022.08.21 |