[Express] Session으로 인증 구현하기_2

2023. 8. 22. 19:24공부 중/Node.js

0. 출처

 

 

express-session을 이용한 인증구현 - 생활코딩

수업소개  express-session을 이용해서 로그인/로그아웃/접근제어 기능을 갖춘 웹애플리케이션을 제작하는 방법을 함께 살펴보겠습니다.  강의1 - 로그인 링크 만들기 소스코드 변경사항 강의2 - 인

opentutorials.org

 

오픈튜토리얼 생활코딩 참고.

 


1. UI 반영

 

// ./lib/auth.js
module.exports.statusUI = (req, res, next)=>{
    let authStatusUI = `<a href="/auth/login">login</a>`;
    if(req.session.is_logined){
        authStatusUI = `${req.session.nickname} - <a href="/auth/logout">logout</a>`
    }
    req.authStatusUI = authStatusUI;
        next();
}

로그인 상태에 따라서 다른 authStatusUI를 생성함.

 

// ./lib/template.js
module.exports.HTML= (req,res,next)=>{
const html = `
    ...
    <body>
        <div id="top">
            <h1><a href="/">Board</a></h1>
        <input id="nightDayBtn" type="button" value="night" onclick="changeDarkMode()"/> 
        ${req.authStatusUI}   //변경
      </div>

html에 req.authStatusUI를 추가한다.

 

// ./routes/index.js, ./routes/topic.js, ./routes/auth.js
const auth = require('../lib/auth')

//모든 get method에 auth.statusUI를 추가.
router.get('/', (req,res,next)=>{
    ...
  next();
},[auth.statusUI,template.List,template.HTML]);

모든 get method에 auth.statusUI 미들웨어를 추가한다.

 

login 상태 logout 상태

 

세션 데이터를 읽어서 로그인한 상태인지 확인한다.

 

로그인한 경우 닉네임과 logout 링크를 보여준다.

 

로그인하지 않은 경우는 login 링크를 보여준다.

 


2. 로그아웃

 

logout 링크를 클릭하면 실제로 로그아웃하도록 만들자.

// ./routes/auth.js
...
router.get('/logout', (req, res, next)=>{
  req.session.destroy((err)=>{
    if(err) console.log(err);
    res.redirect('/');
  });
})

Session.destory()를 사용해서 세션을 삭제한다.

 

그런 다음 /로 리다이렉션 한다.

 

 

세션이 삭제되었다.

 


3. 접근 제어

 

  1. 로그인했을 때만 /에서는 create가, /topic/...에서는 create, update, delete 버튼이 보이도록 하자.
  2. post로 create, update, delete 요청이 들어오면 로그인했는지 확인하고 요청을 처리한다.
  3. 만약 로그인 되어있지 않다면 /auth/login으로 리다이렉션 시키자.

 

가. 로그인 했을때만 버튼이 보이도록 수정

// ./routes/index.js
router.get('/', (req,res,next)=>{
  req.title = "Welcome :)";
  req.desc = "Here is for to test node.js server :)";
  req.control = `
    <input type="button" value="create" onclick="redirect(this,'')"/>
  `;
  req.author = '';
  next();
},[auth.statusUI,template.List,template.HTML]);
// ./routes/topic.js
router.get('/:pageId', (req, res, next)=>{
    ...
  req.control = `
  <input type="button" value="create" onclick="redirect(this, '')"/>
  <input type="button" value="update" onclick="redirect(this, '${pageId}')"/>
  <form id="frm" action="/topic/delete" method="post" style="display:inline">
    <input type="hidden" name="id" value="${pageId}">
    <input type="button" value="delete" 
    onclick="if(confirm('really delete?')==true){document.getElementById('frm').submit();}">
  </form>
  `;
  req.author = `${topic[0].name} 작성`;
  next();
},template.HTML);

create, update, delete 버튼은 req.control에 위치한다.

 

req.control = '';
if(req.session.is_logined) req.control = `...`;

위와 같이 수정한다.

 

login 상태에서는 버튼이 보임. logout 상태에서는 버튼이 보이지 않음.

 


나. POST 요청이 들어오면 로그인 했는지 확인

 

// ./lib/auth.js
...
module.exports.checkLogin = (req, res, next)=>{
    if(req.session.is_logined) next();
    else res.redirect('/auth/login');
}

로그인 상태면 계속 진행하고, 그렇지 않으면 로그인 화면으로 리다이렉션 한다.

 

// ./routes/topic.js
router.route('/create')
  .post(auth.checkLogin, (req,res,next)=>{

...

router.post('/update',auth.checkLogin, (req,res,next)=>{

...

router.post('/delete', auth.checkLogin, (req,res,next)=>{

post 요청을 처리하기 전에 auth.checkLogin을 실행한다.

 

세션 ID를 저장하고 있는 쿠키를 삭제하고 게시물 삭제 시도.

 

로그인 상태가 아니면 게시물을 삭제하지 않고 사용자를 로그인화면으로 리다이렉션 함.

 

정상적으로 동작했지만 login 링크는 버그가 발생함.

 

버그가 발생한 이유는 ./routes/auth.jsauth.statusUI를 추가하지 않았기 때문이다.

 

router.route('/login')
  .get(auth.statusUI,template.List,(req,res,next)=>{

 


4. 세션 저장

 

 

[Express] Session이란?

1. 세션 앞서 쿠키를 사용해서 인증을 구현하면 생기는 문제점에 대하여 알아보았다. [Node.js] 쿠키의 한계 1. 인증 부분의 한계 민감한 정보를 클라이언트 쪽에 저장한다는 것은 위험하다. 또한

ramen4598.tistory.com

 

req.session.save(function(err){…}) : 세션을 store에 저장. 해당 메서드는 session 데이터의 변경이 발생하면 HTTP response의 마지막에 자동적으로 호출된다. 그래서 일반적으로 사용할 일이 없다. 하지만 리다이렉션, long-lived requests, webSocket을 사용할 경우 호출해야 할 수 있다.

즉, 응답을 보내기 전에 세션 변경사항이 저장소에 반영되도록 할 수 있습니다.

 

일전에 session.save() 관하여 공부했었다.

 

지금 코드에는 redirect()session.save()가 동시에 실행된다.

 

운이 나쁘면 수정된 세션 데이터가 반영되기 전에 리다이렉션이 실행될 수 있다.

 

이런 문제를 해결하기 위해서 session.save()를 추가한다.

 

// ./routes/auth.js

router.route('/login')
  .get(auth.statusUI, template.List,(req,res,next)=>{
        ...
  },template.HTML)
  .post((req,res,next)=>{
    ...
    if(email == authData.email && password == authData.password){
      req.session.is_logined = true;
      req.session.nickname = authData.nickname;
            req.session.save((err)=>{
        if(err) console.log(err);
        //res.redirect('/');
          res.send(`<script>window.alert("삑! ${authData.nickname}님 환영합니다.");window.location.href = '/';</script>`);
      });
    }else{
      res.send(`<script>window.alert("삐빅! 틀렸습니다. 다시 시도하세요");window.location.href = '/auth/login';</script>`);
    }
  });
  • req.session.save((err)=>{...}); : 저장 후 콜백 함수 실행.

 


'공부 중 > Node.js' 카테고리의 다른 글

[Express] Passport.js 시작하기  (0) 2023.09.17
[Express] Passport.js이란?  (0) 2023.09.17
[Express] Session으로 인증 구현하기_1  (0) 2023.08.22
[Express] Session이란?  (0) 2023.08.19
[Node.js] 쿠키의 한계  (0) 2023.08.10