[WEB] 쿠키(Cookie) in Express

June hyoung Park·2020년 12월 13일
1

NodeJs

목록 보기
8/9
post-thumbnail

현대의 웹은 HTTP 프로토콜로 이루어져있고, HTTP가 가지는 비연결성(Connectionless)과 비상태성(Stateless) 특성 때문에 사용자와의 연결이 유지되지않고, 연결 해제 후에도 상태 정보를 저장하지않는다. 물론 서버의 자원 절약이라는 장점도 있지만, 사용자 식별이 불가하기 때문에 매번 새로운 사용자로 인식하는 단점이 있지만, 쿠키(Cookie) 및 세션(Session) 인증 방식을 통해 클라이언트의 상태정보를 지속적으로 가져오고, 이에 알맞는 정보 및 화면을 제공할 수 있으며, HTTP의 비상태, 비연결 적인 특성들을 보완할 수 있다.

쿠키(Cookie)

쿠키는 사용자의 정보들을(이름, 값, 만료 날짜/시간(쿠키 저장기간), 경로 정보 등) 사용자의 웹 브라우저에 key, value 형태로 저장 하고 사용자가 요청을 할때 마다 서버에서 생성해준 쿠키를 함께 보내서 서버가 사용자를 식별할 수 있게 해준다. 이로써 로그인 기능도 이용할 수 있고 로그인 이후에도 매 요청마다 사용자에 게 알맞는 정보를 제공할 수 있게 된다.

만료 날짜/시간 유무로 쿠키는 세션쿠키와 지속 쿠키로 분류되며, 지속 쿠키는 파일 형태로 저장되어 브라우저종료 후에도 지속적으로 저장되어 있기에 주기적으로 방문하는 사이트에 대한 설정 정보나 로그인 이름을 유지하려고 사용되며, 세션쿠키는 브라우저 메모리에 저장되므로 브라우저가 종료되면 사라지는 특성을 갖고 있기 때문에 사이트를 탐색할 때, 관련 설정 및 특정 사항들을 임시로 저장하는 쿠키다.

작동 방식 예

  1. 사용자가 웹사이트에서 로그인을 한다.(POST)
  2. request body에 담겨져있는 데이터를 통해 DB를 조회한다.
  3. DB 조회에 성공했다면, HTTP 헤더에 쿠키를 포함 시켜 응답한다.(200)
  4. 로그인 이후 사용자가 다른 요청을 할 경우 서버는 사용자의 쿠키가 유효한지 검사를 하며, 사이트에 재 접속 하더라도 남아있는 쿠키를 이용하여 쿠키가 유효하다면 아이디 및 패스워드 값 없이 인증 완료 처리를 해준다.

In Express

login.js / express

const { Users } = require("../../models");

module.exports = {
  post: async (req, res) => {
    const userInfo = await Users.findOne({
      where: { userId: req.body.userId, password: req.body.password },
    });
    if (!userInfo) {
      return res.status(400).json({ message: "not authorized" });
    }
    res
      .status(200)
      .append(
        "Set-Cookie",
        `id=${req.body.userId}; Path=/; HttpOnly; Secure; SameSite=None;`
      )
      .json({ message: "ok" });
  },
};

클라이언트단에서 로그인 시 body에 담겨저온 정보들로 DB 조회 후 해당 유저가 가입된 유저라면 200 상태코드와 함께 브라우저 쿠키에 해당 유저를 식별할 수 있는 정보를 넣어서 저장한다.

userInfo.js / express

const { Users } = require("../../models");

module.exports = {
  get: async (req, res) => {
    if (!req.cookies.id) {
      return res.status(400).send({ data: null, message: "not authorized" });
    } else {
      let userInfo = await Users.findOne({
        where: { userId: req.cookies.id },
      });
      res.status(200).json({ data: userInfo.dataValues, message: "ok" });
    }
  },
};

로그인 후 유저가 유저 정보에 접근시엔 쿠키에서 id라는 값을 빼온 후 이를 DB와 비교하여 유효할 시 해당 유저의 정보를 반환해준다. 이때 cookie-parser 미들웨어를 통해 req.cookies같은 형식으로 손 쉽게 쿠키를 추출할 수 있다.

Client (React)

async loginRequestHandler() {
    await axios.post(
      "https://localhost:4000/users/login",
      {
        userId: this.state.username,
        password: this.state.password,
      },
      { withCredentials: true }
    );
    this.props.loginHandler(); //setState({isLogin : true})
  
    const { data } = await axios.get("https://localhost:4000/users/userinfo", {
      withCredentials: true,
    });
    this.props.setUserInfo(data.data);
  }

테스트를 위한 간단한 로그인 함수이다. 유저가 form에 입력한값은 POST요청을 통해 서버로 전달되고, 서버와 클라이언트가 다른 도메인을 사용하고 있기에, axios.post 메서드의 3번째 인자로 { withCredentials: true } 옵션을 추가해 주었다. login인증이 끝나면 userinfo에 GET요청을 보내게되고, 요청 성공 시 반환된 유저 정보를 setUserInfo 함수를 통해 업데이트해준다.

profile
Take me home~~~~

0개의 댓글