강의

멘토링

커뮤니티

인프런 커뮤니티 질문&답변

노은빈님의 프로필 이미지
노은빈

작성한 질문수

passport 모듈 배포 후 쿠키 저장 문제

작성

·

352

·

수정됨

0

안녕하세요!! 현재 프론트는 vue.js 백은 node.js로 개발중에 있는데요

공식 문서랑 제로초님 책 보고 따라하면서 하고 있는데

passport를 사용해서 로그인 로직을 구현했습니다

로컬에서는 쿠키 저장도 잘 되고 로그인도 잘 되는데

배포만 하면 쿠키가 생기기는 하는데 저장이 안 돼서 deserialize 가 안되어 로그인 자체가 안 되고 있습니다ㅜ

세션이 문제인가 싶어서 이번에 cookie-session으로 바꿔봤는데도 로컬에서는 되고 배포후에는 안 되고 있습니다.

배포 사이트는 둘 다 cloudtype으로 했고 도메인도 사서 설정을 해봤는데 안 됩니다ㅜㅜ

 

app.js 파일입니다

const express = require("express");
const cookieParser = require("cookie-parser");
const path = require("path");
const mysql = require("mysql2");
const dotenv = require("dotenv");
const morgan = require("morgan");
const session = require("express-session");
const MySQLStore = require("express-mysql-session")(session);
const passport = require("passport");
const bodyParser = require("body-parser");
const cookieSession = require('cookie-session')
const cors = require("cors");

dotenv.config({ path: path.join(__dirname, "/.env") });

const { sequelize } = require("./models");
const app = express();

const passportConfig = require("./passport");
passportConfig(); // 패스포트 설정

// 인증 라우터
const pageRouter = require("./routes/pages");
const authRouter = require("./routes/auth");
const mypageRouter = require("./routes/mypage");
const groupRouter = require("./routes/group");
const guestRouter = require("./routes/guest");
const randomRouter = require("./routes/random");

sequelize
  .sync({ force: false })
  .then(() => {
    console.log("데이터베이스 연결");
  })
  .catch((err) => {
    console.error(err);
  });

const port = 3000;

// VARIABLES
app.set("trust proxy", 1);

app.use(
  cors({
    // front 서버인 127.0.0.1:8080 의 요청을 허용하도록 cors 사용
    origin: [process.env.FRONT_URL_1, process.env.FRONT_URL_2],
    // origin: ['http://localhost:8080', 'http://localhost:8081'],
    methods: ["GET", "PUT", "POST", "PATCH", "DELETE", "OPTIONS"],
    optionsSuccessStatus: 200,
    credentials: true,
  })
);

app.use("/uploads", express.static("uploads"));

app.use(morgan("dev")); // log
app.use(express.static(path.join(__dirname, "public"))); // 요청시 기본 경로 설정

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(cookieParser(process.env.COOKIE_SECRET));

const options = {
  host: process.env.DB_HOST,
  port: process.env.DB_PORT,
  user: process.env.DB_USERNAME,
  password: process.env.DB_PASSWORD,
  database: process.env.DB_DATABASE,
};

// Sequelize로 설정한 MySQL 연결 객체를 사용하여 MySQL 저장소 생성
const sessionStore = new MySQLStore(options, mysql.createConnection(options));

app.use(cookieSession({
  maxAge : 1000 * 60 * 60 * 24 * 7,
  secret: process.env.COOKIE_SECRET, // 암호화 키
  domain: [process.env.FRONT_URL_1, process.env.FRONT_URL_2],
  httpOnly: true,
  secure: true,
  sameSite: "none",
}));

// 쿠키 세션 미들웨어 등록
// regenerate & save 오류 현상 해결
app.use(function(req, res, next) {
  if (req.session && !req.session.regenerate) {
      req.session.regenerate = (cb) => {
          cb()
      }
  }
  if (req.session && !req.session.save) {
      req.session.save = (cb) => {
          cb()
      }
  }
  next()
})

// app.use(
//   session({
//     resave: false, // 세션 항상 저장할지
//     saveUninitialized: true, // 세션 저장 전 Uninitialized 상태로 만들어 저장
//     secret: process.env.COOKIE_SECRET, // 암호화 키
//     store: sessionStore, // Sequelize로 설정한 MySQL 저장소를 사용
//     // cookie: {
//     //   domain: [process.env.FRONT_URL_1, process.env.FRONT_URL_2],
//     //   httpOnly: true,
//     //   secure: true,
//     //   sameSite: "none",
//     //   maxAge: 1000 * 60 * 60 * 24 * 7,
//     // },
//   })
// );

app.use(passport.initialize()); //요청 (req 객체) 에 passport 설정
app.use(passport.session()); // req.session 객체에 passport 인증 완료 정보를 저장

// 경로 지정
app.use("/", pageRouter);
app.use("/auth", authRouter);
app.use("/mypage", mypageRouter);
app.use("/group", groupRouter);
app.use("/guest", guestRouter);
app.use("/random", randomRouter);

// 일부러 에러 발생시키기 TEST용
app.use((req, res, next) => {
  const error = new Error(`${req.method} ${req.url} 라우터가 없습니다.`);
  error.status = 404;
  next(error);
});
app.use((err, req, res, next) => {
  // 404 오류인 경우
  if (err.status === 404) {
    res.status(404).send("페이지를 찾을 수 없습니다.");
  } else {
    // 다른 오류일 경우 일반적인 오류 페이지 표시
    res.status(500).send("서버 오류가 발생했습니다.");
  }
});

// 에러 처리 미들웨어
app.use((err, req, res, next) => {
  // 템플릿 변수 설정
  res.locals.message = err.message;
  res.locals.error = process.env.NODE_ENV !== "production" ? err : {}; // 배포용이 아니라면 err설정 아니면 빈 객체

  res.status(err.status || 500);
  res.send({
    error: {
      message: err.message,
    },
  });
});

app.listen(port, () => {
  console.log(`http://localhost:${port}`);
});

auth.js 파일입니다(로그인 , 로그아웃)

// 로그인
exports.login = async (req, res, next) => {
  //? local로 실행이 되면 localstrategy.js를 찾아 실행
  console.log("로그인 실행");
  passport.authenticate("local", (authError, user, info) => {
    console.log("로그인 패스포트");
    console.log(authError, user, info);
    // done(err)가 처리된 경우
    if (authError) {
      console.error(authError);
      return next(authError); // 에러처리 미들웨어로 보낸다.
    }

    if (!user) {
      return res.status(400).json({ message: "가입되지 않은 회원입니다." });
    }
    console.log('유저',user);

    return req.login(user, (loginError) => {
      if (loginError) {
        console.error(loginError);
        return next(loginError);
      }
      // req.session.save(() => {
        const userData = JSON.parse(JSON.stringify(user));
        delete userData.password;
        console.log('유저데이터', userData);
        res.json({ message: '로그인 성공', user: userData });
      // });
    });
  })(req, res, next); // 미들웨어 내의 미들웨어에는 (req, res, next)를 붙입니다.
};

//로그아웃
// exports.logout = (req, res) => {
//   req.logout(() => {
//     req.session.destroy(); // passport 업데이트 이후 함수 안에 넣어야 실행됨
//     res.clearCookie("connect.sid"); // connect.sid 쿠키 삭제
//     res.send("로그아웃");
//   });
// };
exports.logout = (req, res) => {
  req.session = null; // 세션 삭제
  res.clearCookie("connect.sid"); // connect.sid 쿠키 삭제
  res.send("로그아웃");
};

가비아에서 도메인을 사서 cloudflare로 연결했습니다
화면 캡처 2023-10-20 181801.png프론트에는 'https://api.smile-mbti.shop/ '로 백엔드url를 연결했고

백에는 'https://www.smile-mbti.shop', 'https://front.smile-mbti.shop'을 fronturl로 연결했습니다(쿠키, CORS 도메인)


https://github.com/w00ye0l/SMilE
깃허브 링크도 첨부합니다ㅜ

답변 1

0

안녕하세요 노은빈님, 인프런 AI 인턴이에요.

쿠키 관련 문제로 로그인이 잘 되지 않는 상황이라고 이해하고 있습니다. 문제 해결을 위해 다음과 같은 점들에 주의해 보실 수 있을 것 같습니다:

  1. 동일한 도메인이라면 쿠키의 SameSite 속성을 “None”으로 설정해야 합니다. 이를 위해 사용하는 cookie-parserexpress-session 패키지에서 sameSite 옵션을 “None”으로 설정해주셔야 합니다.

  2. 배포된 사이트의 프론트엔드와 백엔드 서버 간의 도메인이 다르다면, CORS와 관련된 설정도 제대로 확인하셔야 합니다. 프론트엔드 서버에서 백엔드 서버로의 요청 시 쿠키를 전송할 수 있도록 crossOriginResourcePolicy 속성 등을 설정해주셔야 합니다.

  3. 배포된 사이트의 프론트엔드와 백엔드 서버 간의 시간 동기화 문제가 발생할 수 있으므로, 두 서버의 시간을 동기화하거나 시간 관련 문제를 최소화할 수 있도록 작업하셔야 합니다.

위의 사항들을 확인하고 필요한 조치를 취해보시기 바랍니다. 문제가 계속되면 더 자세한 로그나 에러 메시지를 확인하여 원인을 파악하는 것이 도움이 될 수 있습니다. 감사합니다!

노은빈님의 프로필 이미지
노은빈

작성한 질문수

질문하기