Validation이란 무엇인가?
특별한게 아니지만 개발을 하면서 가장 중요한것중 하나입니다. Validation은 말 그대로 어떤것을 검증한다고 보면 됩니다.
function is1(value) {
return value === 1;
}
위 코드는 단순히 값이 1인지 아닌지 판단해서 Boolean 타입의 값을 반환하는 함수입니다.
이렇게 단순한 함수조차 Validation. 즉, 검증을 위한 코드가 됩니다.
라이브러리 joi가 그 예가 될 수 있습니다.
joi - npm (npmjs.com)
joi.dev - 17.4.2 API Reference
나중에 로그인구현에서 쓰게 될 예정입니다.
JWT
- JSON 형태의 데이터를 안전하게 교환하여 사용할 수 있게 해줍니다.
- 인터넷 표준으로서 자리잡은 규격입니다.
- 여러가지 암호화 알고리즘을 사용할 수 있습니다.
- header.payload.signature 의 형식으로 3가지의 데이터를 포함한다. (개미처럼 머리, 가슴, 배) 때문에 JWT 형식으로 변환 된 데이터는 항상 2개의 . 이 포함된 데이터여야 합니다.
- header(머리)는 signature(배)에서 어떤 암호화를 사용하여 생성된 데이터인지 표현합니다.
- payload(가슴)는 개발자가 원하는 데이터를 저장합니다.
- signature(배)는 이 토큰이 변조되지 않은 정상적인 토큰인지 확인할 수 있게 도와줍니다.
- JWT는 암호 키를 몰라도 Decode가 가능합니다. 변조만 불가능 할 뿐, 누구나 복호화하여 보는것은 가능하다는 의미가 됩니다!
- 때문에 민감한 정보(개인정보, 비밀번호 등)는 담지 않도록 해야합니다.
- 특정 언어에서만 사용 가능한것은 아닙니다! 단지 개념으로서 존재하고, 이 개념을 코드로 구현하여 공개된 코드를 우리가 사용하는게 일반적입니다.
정보열람(decode) 누구나 가능하지만
발급하는 것도 검증하는 것도 서버만 가능
기본세팅
$ npm i express mongoose jsonwebtoken joi -S
//익스프레스와 몽구스 jwt joi를 한번에 설치해 준다.
간단한 jwt인증 미들웨어를 구현해 보았다.
const jwt = require("jsonwebtoken");
const User = require("../models/user")
module.exports = (req, res, next) => {
const { authorization } = req.headers;
const [toKenType, tokenValue] = authorization.split(' ');
console.log(tokenValue)
if (toKenType !== 'Bearer'){
res.status(401).send({
errorMessage: '로그인 후 사용하세요',
})
return;
}
try {
const { userId } = jwt.verify(tokenValue, "my-secret-key");
User.findById(userId).then((user)=> {
res.locals.user = user;
next();
});
} catch (error) {
res.status(401).send({
errorMessage: "로그인 후 사용하세요",
})
return
}
}
joi 라이브러리를 이용해서 간단히 로그인과 회원가입 페이지를 만들어 보았다.
const postUsersSchema = Joi.object({
nickname: Joi.string().required(),
email: Joi.string().email().required(),
password: Joi.string().required(),
confirmPassword: Joi.string().required(),
})
router.post("/users", async (req, res) => {
try{
const { nickname, email, password, confirmPassword } = await postUsersSchema.validateAsync(req.body);
if (password !== confirmPassword) {
res.status(400).send({
errorMessage: "패스워드가 패스워드 확인란과 동일하지 않습니다.",
});
return;
}
const existUsers = await User.find({
$or: [{ email }, { nickname }],
});
if (existUsers.length) {
res.status(400).send({
errorMessage: "이미 가입된 이메일 또는 닉네임이 있습니다.",
});
return;
}
const user = new User({ email, nickname, password });
await user.save();
res.status(201).send({});
} catch(err) {
console.log(err)
res.status(400).send({
errorMessage: "요청한 데이터 형식이 올바르지 않습니다.",
})
}
});
const postAuthSchema = Joi.object({
email: Joi.string().email().required(),
password: Joi.string().required(),
})
router.post("/auth", async (req, res) => {
try{
const { email, password } = await postAuthSchema.validateAsync(req.body);
const user = await User.findOne({ email, password }).exec();
if (!user) {
res.status(400).send({
errorMessage: "이메일 또는 패스워드가 잘못됐습니다.",
});
return;
}
const token = jwt.sign({ userId: user.userId }, "my-secret-key");
res.send({
token,
});
} catch (err) {
res.status(400).send({
errorMessage: "요청한 데이터 형식이 올바르지 않습니다.",
})
}
});
'Today I Learned' 카테고리의 다른 글
TIL은 노션과 깃허브로 옮기기로 했습니다! (0) | 2021.10.10 |
---|---|
16 TIL 소켓 socket.io 쇼핑몰 실시간 구매 알림 기능 (0) | 2021.10.02 |
13 TIL node aws 배포 명령어, 처음 시작 시 github remote add commit push 하기 (0) | 2021.09.30 |
12 TIL 리액트 박살내기! (0) | 2021.09.29 |
11 TIL 리액트의 날 (0) | 2021.09.27 |