REACT. Node.js Netflix App | Netflix 클론 코딩 (5)
1. LOGIN
auth.js
router.post("/login", async (req, res) => {
try {
} catch {
}
});
로그인 할 수 있게 "/login" 경로를 지정해주고 async, await로 비동기 처리 하고 try,catch 하자!
가독성을 위해 try, catch만 따로 빼서 보려고 했는데 가독성이 더 안좋아진 것 같다
try {
const user = await User.findOne({ email: req.body.email });
!user && res.status(401).json("Wrong password or username!");
res.status(200).json();
} catch (err) {
res.status(500).json(err);
}
1) email로 user을 찾자
2) user이 없으면(false이면) json에 이걸 출력하가
3) 자체 에러가 없으면 status(200), 자체 에러가 있으면 status(500)
암호화의 반대, decrypt를 하자 (그래야 비밀번호가 맞는지 안맞는지 확인이 가능하다)
// decrypt( <-> encrypt)
const bytes = CryptoJS.AES.decrypt(user.password, process.env.SECRET_KEY);
const originalPassword = bytes.toString(CryptoJS.enc.Utf8);
originalPassword !== req.body.password &&
res.status(401).json("Wrong password or username!");
마지막으로 json으로 불러 올 때, 암호를 빼고 불러오자(보안보안)
const { password, ...info } = user._doc;
res.status(200).json(info);
전체를 보면 다음과 같다
router.post("/login", async (req, res) => {
try {
const user = await User.findOne({ email: req.body.email });
!user && res.status(401).json("Wrong password or username!");
// decrypt( <-> encrypt)
const bytes = CryptoJS.AES.decrypt(user.password, process.env.SECRET_KEY);
const originalPassword = bytes.toString(CryptoJS.enc.Utf8);
originalPassword !== req.body.password &&
res.status(401).json("Wrong password or username!");
const { password, ...info } = user._doc;
res.status(200).json(info);
} catch (err) {
res.status(500).json(err);
}
});
2. JWT(존맛탱 아니... JSON WEB TOKEN)
auth.js
jsonwebtoken을 호출하고, catch안에 accessToken를 설정하자!
accessToken 안에는 id, isAdmin, SECRET_KEY, 만료일이 들어간다
const jwt = require("jsonwebtoken");
catch {
const accessToken = jwt.sign(
{ id: user._id, isAdmin: user.isAdmin },
process.env.SECRET_KEY,
{ expiresIn: "5d" }
);
const { password, ...info } = user._doc;
res.status(200).json({ ...info, accessToken });
}
postman에서 send를 누르면, 이전과 다르게 accessToken도 같이 불러와진다
3. REST API User CRUD Operations(Update)
거창한 제목을 썼지만 사실 별거 없다
회원정보를 어떻게 수정할까?를 의미한다
verifyToken.js
기본구조
const jwt = require("jsonwebtoken");
function verify(req, res, next) {}
module.exports = verify;
authHeader이 있다면 accessToken을 비교,
authHeader이 없다면 "You are not authenticated"라 출력
accessToken을 사용가능한 Token이라면 next()를 통해 판단을 다음으로 유보하고
accseeToken을 사용가능하지 않는 Token이라면, "Token is not valid!"라 한다
const jwt = require("jsonwebtoken");
function verify(req, res, next) {
const authHeader = req.headers.token;
if (authHeader) {
const token = authHeader.split(" ")[1];
jwt.verify(token, process.env.SECRET_KEY, (err, user) => {
if (err) res.status(403).json("Token is not valid!");
req.user = user;
next();
});
} else {
return res.status(401).json("You are not authenticated");
}
}
module.exports = verify;
/routes/user.js
호출할거 호출하고 한 기본구성이다
const router = require("express").Router();
const User = require("../models/User");
const CryptoJS = require("crypto-js");
const verify = require("../verifyToken");
// UPDATE
module.exports = router;
'// UPDATE' 안을 채워줄 것이다
경로는 /:id, verify를 스쳐지나감(거기서 next()한다)
(req.user.id)와 (req.params.id) or (req.user.isAdmin)이 같다면 올바른 일을 수행하고,
아니면 403을 띄운다
// UPDATE
router.put("/:id", verify, async (req, res) => {
if (req.user.id === req.params.id || req.user.isAdmin) {
// 올바른 일 수행
} else {
res.status(403).json("You can update only your account!");
}
});
아래는 올바른 일을 수행할 때의 코드이다
// 올바른 일 수행
if (req.body.password) {
req.body.password = CryptoJS.AES.encrypt(
req.body.password,
process.env.SECRET_KEY
).toString();
}
try {
const updatedUser = await User.findByIdAndUpdate(
req.params.id,
{$set: req.body,}, {new: true,}
);
res.status(200).json(updatedUser);
} catch (err) {
res.status(500).json(err);
}
{$set: req.body} -> 업데이트 해준다
{new: true} -> 새로운 내용으로 업데이트