첫번째로 작업한 controller는 회원가입과 로그인 이다.
회원가입을 할때는 클라이언트에서 username과 eamil, password를 보내준다.
import { Request, Response } from "express";
import { getConnection } from "typeorm";
import { getManager } from "typeorm";
import User from "../../entity/User";
import crypto from "crypto";
export default async (req: Request, res: Response) => {
const email = req.body.email;
const password = req.body.password;
const username = req.body.username;
if (!email || !password || !username) {
res.status(422).send({ message: "insufficient parameters supplied" });
}
const isemail = await getManager()
.createQueryBuilder(User, "User")
.where({ email: email })
.getOne();
if (isemail) {
res.status(409).send({ message: "email exists" });
} else {
const createSalt: Function = () =>
new Promise((resolve, reject) => {
crypto.randomBytes(64, (err, buf) => {
if (err) reject(err);
resolve(buf.toString("base64"));
});
});
const createHashedPassword: Function = (plainpassword) =>
new Promise(async (resolve, reject) => {
const salt = await createSalt();
crypto.pbkdf2(plainpassword, salt, 1000, 64, "sha512", (err, key) => {
if (err) reject(err);
resolve({ hashPwd: key.toString("base64"), salt });
});
});
const { hashPwd, salt } = await createHashedPassword(password);
await getConnection()
.createQueryBuilder()
.insert()
.into(User)
.values({
email: email,
password: hashPwd,
username: username,
darkMode : false,
siteColor : "random",
salt: salt,
})
.execute();
res.status(201).send({ message: "Sign successfully" });
}
};
요구하는 3가지 값이 들어오면 먼저 password를 암호화 하는 작업을 한다. slat를 생성하고 생성한 salt와 hash 함수를 이용 하여 암호화를 하고 디비에 저장한다.
사이트 옵션인 darkMode와 siteColr는 디폴트 값으로 저장하고 , username과 email, password는 클라에서 보내준 값으로 저장한다.
디비에 저장 할때는 typeorm을 사용하였다.
import { Request, Response } from "express";
import { getManager } from "typeorm";
import User from "../../entity/User";
import crypto from "crypto";
import "dotenv/config";
import jwt from 'jsonwebtoken'
export default async (req: Request, res: Response) => {
const email: string = req.body.email;
const password: string = req.body.password;
const user = await getManager()
.createQueryBuilder(User, "User")
.where({ email: email })
.getOne();
if (!user) {
res.status(400).send({ data: null, message: "not authorized" })
} else {
const { salt } = user;
const createHashedPassword = (plainpassword: string) =>
new Promise(async (resolve, reject) => {
crypto.pbkdf2(plainpassword, salt, 1000, 64, 'sha512', (err, key) => {
if (err) reject(res.status(400).send({ message: "hashPwd exists" }));
resolve(key.toString('base64'));
});
});
const hashPwd = await createHashedPassword(password);
const userInfo = await getManager()
.createQueryBuilder(User, "User")
.where({ password: hashPwd })
.getOne()
const accessToken = jwt.sign(
{
'id': userInfo.id,
'username': userInfo.username,
'email': userInfo.email,
'darkMode': false,
'siteColor': "random",
},
process.env.ACCESS_SECRET,
{ expiresIn: '1d' });//하루 뒤 파괴
res.send({ accessToken: accessToken, message: "Login successfully" })
}
};
로그인 할때는 클라에서 보내준 email과 password를 이용한다. 먼저 동일한 이메일이 있는지 확인 하고 이메일이 있으면 그 유저의 salt로 비번을 해쉬함수를 이용하여 암호화를 하고 일치하는 비번이 있는지 찾고 있으면, 토큰을 발급해준다.