해결된 질문
작성
·
92
0
logout을 해보니 400BadRequest:이미 로그아웃 됨 상태가 지속됩니다. console.log(req.cookies.token); 출력해보니 undefined 라고 출력됩니다. 쿠키를 제대로 읽지 못하는것 같은데 왜 이런 현상이 뜨는지 궁금합니다..
const express = require("express");
const router = express.Router();
const bcrypt = require("bcrypt");
const User = require("../models/User");
const axios = require("axios");
const jwt = require("jsonwebtoken");
router.post("/signup", async (req, res) => {
try {
const { username, password } = req.body;
const existingUser = await User.findOne({ username });
if (existingUser) {
return res.status(400).json({ message: "이미 존재하는 사용자입니다." });
}
const hashedPassword = await bcrypt.hash(password, 10);
const user = new User({
username,
password: hashedPassword,
});
await user.save();
res.status(201).json({ message: "회원가입이 완료되었습니다." });
} catch (error) {
res.status(500).json({ message: "서버 오류가 발생했습니다." });
console.log(error);
}
});
router.post("/login", async (req, res) => {
try {
const { username, password } = req.body;
const user = await User.findOne({ username }).select("+password"); //왜인지 password가 select되지 않아서 추가함
if (!user) {
return res.status(401).json({ message: "존재하지 않는 사용자입니다." });
}
if (!user.isActive) {
return res.status(401).json({ message: "비활성화된 사용자입니다." });
}
if (user.isLoggedIn == true) {
return res.status(401).json({ message: "이미 접속 중인 사용자입니다." });
}
const isValidPassword = await bcrypt.compare(password, user.password); //비밀번호 비교
if (!isValidPassword) {
user.failedLoginAttempts += 1;
user.lastLoginAttempt = new Date();
if (user.failedLoginAttempts >= 5) {
user.isActive = false; //다섯번 틀리면 계정 비활성화 ㅋㅋ
await user.save();
return res.status(401).json({
message: "비밀번호를 5회 이상 틀려 계정이 비활성화되었습니다.",
});
}
await user.save();
return res.status(401).json({
message: "비밀번호가 일치하지 않습니다.",
remainingAttempts: 5 - user.failedLoginAttempts,
});
}
user.failedLoginAttempts = 0;
user.lastLoginAttempt = new Date();
user.isLoggedIn = true;
try {
const response = await axios.get("https://api.ipify.org?format=json"); //공공장소 사용금지요
const ipAddress = response.data.ip; //한번 정제함
user.lastLoginIp = ipAddress;
} catch (error) {
console.log("IP 주소를 가져오는데 실패했습니다: ", error.message);
}
await user.save();
const token = jwt.sign(
{ userId: user._id, username: user.username },
process.env.JWT_SECRET,
{ expiresIn: "24h" } //토큰 만료는 24시간
);
console.log(token); //오 된다
res.cookie("token", token, {
httpOnly: true, //자바스크립트에서 쿠키 접근 불가
secure: "production", //https에서만 쿠키 전송
sameSite: "strict", //같은 사이트에서만 쿠키 전송
maxAge: 24 * 60 * 60 * 1000, //24시간
});
const userWithoutPassword = user.toObject(); //구글링 해보니 이렇게 하면 문서 타입을 일반 객체로 변환할 수 있다고 한다
delete userWithoutPassword.password; //보안때문에 비밀번호는 삭제할 수 있다고 한다
res.json({ user: userWithoutPassword });
} catch (error) {
console.log("서버 오류: ", error);
res.status(500).json({ message: "서버 오류가 발생했습니다." });
}
});
router.post("/logout", async (req, res) => {
console.log(req.cookies.token);
try {
const token = req.cookies.token;
if (!token) {
return res.status(400).json({ message: "이미 로그아웃된 상태입니다." });
}
try {
const decoded = jwt.verify(token, process.env.JWT_SECRET);
const user = await User.findById(decoded.userId);
if (user) {
user.isLoggedIn = false;
await user.save();
}
} catch (error) {
console.log("토큰 검증 오류: ", error.message);
}
res.clearCookie("token", {
httpOnly: true,
secure: "production",
sameSite: "strict",
});
res.json({ message: "로그아웃되었습니다." });
} catch (error) {
console.log("로그아웃 오류: ", error.message);
res.status(500).json({ message: "서버 오류가 발생했습니다." });
}
});
router.delete("/delete/:userId", async (req, res) => {
try {
const user = await User.findByIdAndDelete(req.params.userId);
if (!user) {
return res.status(404).json({ message: "사용자를 찾을 수 없습니다." });
}
res.json({ message: "사용자가 성공적으로 삭제되었습니다." });
} catch (error) {
res.status(500).json({ message: "서버 오류가 발생했습니다." });
}
});
module.exports = router;
답변 1
0
안녕하세요. 질문 남겨주셔서 감사합니다!
백엔드 코드로는 큰 문제가 보이지 않지만 몇 가지 확인해주시면 감사하겠습니다.
관리자 로그인 후 브라우저에 쿠키가 제대로 저장되지 않아서 request에 제대로 전송되지 않았을 가능성이 있습니다.
const express = require("express");
const cookieParser = require("cookie-parser");
const app = express();
app.use(cookieParser()); // 쿠키 파서 미들웨어 추가
cookie-parser를 패키지를 설치 후 프론트엔드에서 전송되는 쿠키 값을 읽을 수 있습니다. 이 부분도 확인 부탁드립니다.
추가적으로, 이것말고 여러가지 해결방법이 있지만 제시된 2가지 방법으로 해결이 어려우시다면 adminLogin.jsx 및 관리자 메뉴바의 로그아웃 부분과 개발자 도구의 캡쳐사진도 부탁드리겠습니다. 감사합니다!
현재 강의에서는 관리자페이지, adminLogin.jsx 생성 전입니다. 일단 거기까지 진행을 하고 답변을 드리면 될까요?
index.js
require("dotenv").config(); const express = require("express"); const mongoose = require("mongoose"); const cookieParser = require("cookie-parser"); const app = express(); const PORT = 3000; const userRoutes = require("./routes/user"); app.use(cookieParser()); app.use(express.json()); app.use(express.urlencoded()); app.use("/api/auth", userRoutes); app.get("/", (req, res) => { res.send("Hello world"); }); mongoose .connect(process.env.MONGO_URI) .then(() => console.log("MongoDB 연결 성공.")) .catch((error) => console.log("MongoDB 연결 실패: ", error)); app.listen(PORT, () => { console.log("Server is running"); });