// (?=.*\d) : 최소한 1개 이상의 숫자가 포함되어야 합니다
// [a-z0-9]+ : 소문자와 숫자로만 이루어져야 합니다
// ^와 $ : 문자열의 시작과 끝을 의미합니다.
const idForm = /^(?=.*[a-z])(?=.*\d)[a-z0-9]+$/;
해당 코드로 수정하여 영어(소문자) + 숫자 가 포함된 형식으로 아이디를 생성하도록 적용하였다.
해당 코드로 수정하여 영어(소문자) + 숫자 가 포함된 형식으로 아이디를 생성하도록 적용하였다.
// 로그인 API
import express from "express";
import { prisma } from "../utils/prisma/index.js";
import bcrypt from "bcrypt";
import jwt from "jsonwebtoken";
const router = express.Router();
router.post("/sign-in", async (req, res) => {
const { id, password } = req.body;
const accounts = await prisma.accounts.findFirst({ where: { id } });
if (!accounts)
return res.status(401).json({ message: "존재하지 않는 id입니다." });
// 입력받은 사용자의 비밀번호와 데이터베이스에 저장된 비밀번호를 비교합니다.
else if (!(await bcrypt.compare(password, accounts.password)))
return res.status(401).json({ message: "비밀번호가 일치하지 않습니다." });
// 로그인에 성공하면, 사용자의 accout_id를 바탕으로 토큰을 생성합니다.
const token = jwt.sign(
{
account_id: accounts.account_id,
},
// JWT를 서명하는 데 사용되는 비밀 키
// 서버가 비밀 키를 사용하여 토큰 변조 여부를 알 수 있다
"server-secret-key",
{ expiresIn: "1h" }
);
return res.status(200).json({ message: "로그인 성공", token });
});
export default router;
추가로 로그인 API에서 로그인 성공 시 토큰을 생성하도록 업데이트하였다.
// 인증 미들웨어 auth.js
import jwt from "jsonwebtoken";
import { prisma } from "../utils/prisma/index.js";
export default async function authM(req, res, next) {
try {
// 클라이언트로부터 요청이 들어오면 req.headers에서 authorization 헤더를 추출
const { authorization } = req.headers;
console.log(authorization);
if (!authorization) throw new Error("토큰이 존재하지 않습니다.");
// authorization 헤더의 값을 공백으로 나누어 tokenType과 token을 추출
const [tokenType, token] = authorization.split(" ");
// tokenType이 "Bearer"인지 검증
if (tokenType !== "Bearer")
throw new Error("토큰 타입이 일치하지 않습니다.");
// jwt.verify 함수를 사용하여 token을 검증
// 비밀 키 "server-secret-key"를 사용하여 토큰의 유효성을 확인
const decodedToken = jwt.verify(token, "server-secret-key");
const accountsId = decodedToken.account_id;
// prisma.accounts.findFirst를 사용하여 db에 account_id가 존재하는지 확인
const accounts = await prisma.accounts.findFirst({
where: { account_id: accountsId },
});
if (!accounts) {
throw new Error("토큰 사용자가 존재하지 않습니다.");
}
// req.accounts 사용자 정보를 저장합니다.
req.abc = accounts;
// 객체 확인
console.log("인증된 정보 :", req.abc);
next();
} catch (error) {
// 토큰이 만료되었거나, 조작되었을 때, 에러 메시지를 다르게 출력합니다.
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 ?? "비정상적인 요청입니다." });
}
}
}
이후 미들웨어 폴더 생성 > 인증 미들웨어를 구현하였다. 로그인 성공 시 생성되는 토큰을 바탕으로 인증을 진행하고, 인증 성공 시 req.abc 객체에 인증된 사용자 정보가 저장된다.
import express from "express";
import { prisma } from "../utils/prisma/index.js";
import authM from "../middlewares/auth.js";
// character.js
const router = express.Router();
// create-character 경로에 대한 POST 요청을 처리하는 API 구성
// authM 미들웨어를 사용하여 인증을 수행
router.post("/create-character", authM, async (req, res) => {
// 요청 본문에서 nickname 추출
const { nickname } = req.body;
// authM 미들웨어에서 인증을 거친 accounts 정보를 가져오고
// accounts에서 account_id를 추출한다
const { account_id } = req.abc;
// 닉네임 중복 검증
const isExistCharacter = await prisma.characters.findFirst({
where: { nickname },
});
if (isExistCharacter) {
return res.status(409).json({ message: "이미 존재하는 닉네임입니다." });
}
// 캐릭터 생성 로직
const newCharacter = await prisma.characters.create({
data: {
// 뽑아온 nickname, account_id를 각 컬럼에 적용한다.
account_id: account_id,
nickname: nickname,
health: 500,
power: 100,
money: 10000,
},
});
return res
.status(201)
.json({ message: "캐릭터 생성 성공", character: newCharacter });
});
export default router;
인증 미들웨어에서 저장된 계정 정보를 토대로, 캐릭터 테이블에 정보를 적용하여 캐릭터를 생성한다.
이 과정 중 미들웨어 적용에 대한 문제를 겪었다. 처음에는 app.js 파일에서 전역적으로 미들웨어를 적용하려고 했고, 이 방법은 모든 라우터에 미들웨어가 적용되기 때문에 인증이 필요하지 않은 요청에도 인증과정이 거쳐지는 문제였다.
그래서 튜터님을 통해 라우터에 개별적으로 미들웨어를 적용하는 방법을 배웠고, 이를 통해 각 라우터의 요구 사항에 맞게 미들웨어를 선택적으로 적용할 수 있게 되었다.
나의 경우에는 미들웨어를 전역적으로 적용하는 것보다 라우터에 개별적으로 적용하는 것이 더 효과적이였다.
'TIL' 카테고리의 다른 글
내일배움캠프 6주차 월요일 TIL (1) | 2024.12.02 |
---|---|
내일배움캠프 5주차 금요일 (1) | 2024.11.29 |
내일배움캠프 5주차 화요일 TIL (0) | 2024.11.26 |
내일배움캠프 5주차 월요일 TIL (0) | 2024.11.25 |
내일배움캠프 4주차 금요일 TIL (0) | 2024.11.22 |