[TIL] express-session

김민재·2023년 11월 30일
0

TIL

목록 보기
80/172
// app.js

import express from 'express';
import expressSession from 'express-session';

const app = express();
const PORT = 3019;

app.use(express.json());
app.use(
  expressSession({
    secret: 'express-session-secret-key.', // 세션을 암호화하는 비밀 키를 설정
    resave: false, // 클라이언트의 요청이 올 때마다 세션을 새롭게 저장할 지 설정, 변경사항이 없어도 다시 저장
    saveUninitialized: false, // 세션이 초기화되지 않았을 때 세션을 저장할 지 설정
    cookie: {
      // 세션 쿠키 설정
      maxAge: 1000 * 60 * 60 * 24, // 쿠키의 만료 기간을 1일로 설정합니다.
    },
  }),
);

app.post("/sessions", (req, res, next) => {
  const { userId } = req.body;

  req.session.userId = userId;

  return res.status(201).json({ message: "세션을 설정했습니다." });
});

app.get("/sessions", (req, res, next) => {
  return res.status(200).json({
    message: "세션을 조회했습니다",
    sessions: req.session.userId ?? null,
  });
});

app.listen(PORT, () => {
  console.log(PORT, '포트로 서버가 열렸어요!');
});

한 유저당 한번만 작동된다.
서버를 껐다가 키면 session이 날라간다.
그래서 db에 session에 저장을 하며 된다.

이전에는 사용자가 로그인 성공 시, JWT를 생성하고 이를 쿠키로 전달하였습니다.

하지만, 저희는 이제 JWT 대신 express-session세션 ID를 사용해보려고 합니다. 로그인이 성공하면 세션 ID를 생성하고, 이를 쿠키로 사용자에게 전달할 예정입니다.

yarn add express-mysql-session
express-session을 MySQL에 저장할 수 있도록 해준다.

미들웨어

// import jwt from "jsonwebtoken";
import { prisma } from "../src/utils/prisma/index.js";

// jwt를 사용하지 않고 express-session을 사용
export default async function (req, res, next) {
  try {
    // const { authorization } = req.cookies;

    // const [tokenType, token] = authorization.split(" ");
    // if (tokenType !== "Bearer")
    //   throw new Error("토큰 타입이 일치하지 않습니다.");

    // // 서버에서 발급한 jwt가 맞는지 검증한다.
    // const decodedToken = jwt.verify(token, "key");

    // const userId = decodedToken.userId;

    const { userId } = req.session;
    if (!userId) throw new Error("로그인이 필요합니다.");

    const user = await prisma.users.findFirst({
      where: { userId: +userId },
    });

    if (!user) {
      // res.clearCookie("authorization");
      throw new Error("토큰 사용자가 존재하지 않습니다."); // catch로 넘긴다.
    }

    // req.user에 user정보를 넣어준다
    req.user = user;

    next();
  } catch (error) {
    res.clearCookie("authorization");
    // 에러 구분
    switch (error.name) {
      // case "TokenExpriredError": // 토큰이 만료되었을 때 발생하는 에러
      //   return res.status(401).json({ message: "토큰이 만료되었습니다." });
      //   break;
      // case "JsonwebtokenEroor": // 토큰에 검증이 실패했을 때 발생하는 에러
      //   return res.status(401).json({ message: "토큰이 검증이 실패했습니다." });
      //   break;
      default:
        return res
          .status(401)
          .json({ message: error.name ?? "비정상적인 요청입니다." });
    }
  }
}

// // src/middlewares/auth.middleware.js

// import jwt from 'jsonwebtoken';
// import { prisma } from '../utils/prisma/index.js';

// export default async function (req, res, next) {
//   try {
//     const { authorization } = req.cookies;
//     if (!authorization) throw new Error('토큰이 존재하지 않습니다.');

//     const [tokenType, token] = authorization.split(' ');

//     if (tokenType !== 'Bearer')
//       throw new Error('토큰 타입이 일치하지 않습니다.');

//     const decodedToken = jwt.verify(token, 'customized_secret_key');
//     const userId = decodedToken.userId;

//     const user = await prisma.users.findFirst({
//       where: { userId: +userId },
//     });
//     if (!user) {
//       res.clearCookie('authorization');
//       throw new Error('토큰 사용자가 존재하지 않습니다.');
//     }

//     // req.user에 사용자 정보를 저장합니다.
//     req.user = user;

//     next();
//   } catch (error) {
//     res.clearCookie('authorization');

//     // 토큰이 만료되었거나, 조작되었을 때, 에러 메시지를 다르게 출력합니다.
//     switch (error.name) {
//       case 'TokenExpiredError':
//         return res.status(401).json({ message: '토큰이 만료되었습니다.' });
//       case 'JsonWebTokenError':
//         return res.status(401).json({ message: '토큰이 조작되었습니다.' });
//       default:
//         return res
//           .status(401)
//           .json({ message: error.message ?? '비정상적인 요청입니다.' });
//     }
//   }
// }

로그인 라우터

router.post("/sign-in", async (req, res, next) => {
  const { email, password } = req.body;

  const user = await prisma.Users.findFirst({
    where: { email },
  });

  if (!user) {
    return res.status(401).json({ message: "존재하지 않는 이메일입니다." });
    // 401 없는
  }

  //   const result = await bcrypt.compare(password, user.password)

  if (!(await bcrypt.compare(password, user.password))) {
    return res.status(401).json({ message: "비밀번호가 일치하지 않습니다." });
  }

  req.session.userId = user.userId;

  // 토큰
  // const token = jwt.sign(
  //   {
  //     userId: user.userId,
  //   },
  //   "key" // 비밀 키는 env에 넣어야 돼
  // );

  // res.cookie("authorization", `Bearer ${token}`);
  // Bearer 하고 %20 이 나오는데 이건 스페이스를 뜻한다.
  return res.status(200).json({ message: "로그인이 완료 되었습니다." });
  // 뭔가를 보낸 게 아니라 200
});
profile
개발 경험치 쌓는 곳

0개의 댓글

관련 채용 정보