세션-쿠키 인증방식은 로그인에서 아직까지도 제일 많이쓰이는 인증 방식이다.
서버쪽에는 세션이라는 저장소를 따로 만들어둔다. 쉽게 생각해서 key value로 이루어진 객체라고 생각하면 좋을 듯 하다.
단순히 express만 사용한다면 하나의 객체를 세션으로 사용할 수 있을 것이다.
단순히 객체를 세션으로 사용해서 로그인을 할 때의 과정을 적어보려고 한다.
유저가 브라우저의 로그인 창에서 로그인 요청을 보낼 것이다.
POST http://localhost:5000/api/user/login
body {id, password}
그러면 서버에서 해당 요청을 받을 것이다.
request.body에 들어온 id와 password로 DB에서 비교한다. 해당 id에 해당하는 유저가 있어야하고, DB에 저장되어있는 hash화 된 비밀번호와 request.body의 password를 hash화한 비밀번호가 같은지를 확인한다. 만약 둘 중 하나라도 다르다면 message: '아이디 또는 비밀번호가 일치하지 않습니다.' 정도의 메시지를 클라이언트로 보내준다. 아이디 또는 비밀번호라고 하는 이유는 보안상 권장되는 사항이기 때문이다.
이제 로그인 유지를 위해서 세션에 유저정보를 저장해둬야한다. 아무의미 없는 랜덤 String을 만들어 key로 지정하고 value로 유저의 정보를 저장해둔다.
{
'adfsdfasdfsdf': {id: 'test', name:'문건우'}
}
이런식으로 저장이 될 것이다.
key를 cookie로 발급해준다. express의 response.cookie를 사용하면 클라이언트 쪽으로 쿠키를 보내줄 수 있다. cookie는 브라우저에 저장된다.
이렇게 하면 로그인 과정은 끝이난다. 그러면 로그인 후 로그인이 필요한 서비스를 이용할 때의 과정을 적어본다.
게시판을 보기 위해서는 로그인이 되어있어야한다고 가정하겠다.
GET http://localhost:5000/api/board
로 cookie와 함께 요청을 보내면 된다. cookie는 form을 사용하면 자동으로, fetch를 사용하면 헤더의 credentials 옵션을 'include'로 해서 보내면 된다.
cookie에는 value 값으로 session의 key 값이 저장되어있다. cookie의 value 값이 session에 저장돼있는지 확인한다. 만약 key 값에 해당하는 유저 정보가 없을 경우에는 로그인이 되어있지 않다고 판단하고 로그인이 필요하다는 메시지를 보내준다.
이제 로그인이 되어있는 것을 확인을 하였으니, 게시판 정보를 DB로부터 가지고 와서 클라이언트로 응답을 해준다.
이런식으로 이루어진다. 세션은 이렇게 객체를 사용해서 할 수도 있지만 express-session이라는 라이브러리를 사용하는 것을 추천한다. 구현에 많은 도움도 주고 보안에도 더 유리하다.
장점: 세션을 사용하면 유저의 정보를 서버에 저장해놓기 때문에 보안상 안전하다. 브라우저의 쿠키에는 의미 없는 값인 string이 들어가 있기 때문에 해당 정보로는 알 수 있는 정보가 없다. 그리고 로그인 서비스에는 대부분 HTTPS로 되어있기 때문에 쿠키를 탈취한다고 해도 정보를 얻어내기 어렵고, 만료시간을 설정함으로써 더욱 보안을 유지할 수 있다.
단점: 세션이 서버의 자원을 사용하기 때문에 서버에 부하가 있을 수 있다.
세션을 메모리에 저장한다고 했을 때, 사용자수가 늘어나서 서버를 스케일 아웃으로 수평적으로 늘렸다고 가정한다. 서버의 대수를 늘린 것이다. 그렇게 세션을 메모리에 저장하게 되면 각각의 서버마다 각각의 세션을 가지게 된다. 그렇게 되면 새로고침을 했을 때 서버에 걸리는 부하를 균등하게 해주는 로드밸런싱 때문에 다른 서버로 배정되게 되어 로그인이 풀려있는 현상이 발생할 수 있다. 이것을 해결하기 위해 레디스 서버를 따로 둬서 사용할 수 있다. 레디스DB에 key, value로 유저의 정보를 저장해두고, 세션처럼 사용하는 것이다. 그러면 스케일 아웃을 했을 경우에도 서버마다 로그인을 일정하게 유지할 수 있다.