라우팅 설정
패스워드를 암호화할 모듈과 jwt 모듈을 설치한다.
1 2 |
yarn add bcryptjs @types/bcryptjs yarn add jsonwebtoken @types/jsonwebtoken |
auth router를 설정한다.
src/router/auth.ts
1 2 3 4 5 6 |
import {Router} from "express"; import {AuthController} from "../controller/AuthController"; const routes = Router(); routes.post('/signin', AuthController.signIn); routes.post('/signup', AuthController.signUp); export default routes; |
AuthController에 signIn과 signUp 은 프로토타입을 미리 만들어 놓아야 에러가 안생긴다.
router 폴더에 index.ts에 auth를 추가한다.
src/router/index.ts
1 2 3 |
... routes.use('/auth', auth); export default routes; |
로그인과 로그아웃 구현
sign up은 이메일과 사용자 이름, 그리고 패스워드 3가지를 입력받아서 사용자 정보를 생성한다. role은 만일 클라이언트에서 지정한 role이 있다면 설정하고 없다면 ROLE_USER를 기본 role로 설정한다.
패스워드는 복호화할 수 없는 비대칭키로 암호화를 해야 하는데 앞에서 bcrypt 모듈을 설치했고 hashSync 함수를 이용해서 복호화 한다.
src/controller/AuthController.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
export class AuthController { static signUp = async (req, res) => { const {email, password, username, roles} = req.body; const user = new User(); user.email = email; user.password = hashSync(password, 8); user.username = username; // 이메일 중복 체크 const existUser = await getConnection().getRepository(User) .findOne({where: {email}}); if (existUser) { return res.status(400).send({ message: "User Not found." }); } user.roles = []; if (roles && roles.length > 0) { // where a 혹은 b or 조건 [{ name: 'a'}, {name: 'b'}] const res = await getConnection().getRepository(Role).find({ where: roles.map(name => ({name})) }) user.roles = res; } else { // 기본 role은 USER const res = await getConnection().getRepository(Role).find({ where: {name: 'ROLE_USER'} }) user.roles = res; } const result = await getConnection().getRepository(User).save(user); res.send(result); } } |
이메일과 패스워드를 입력받아서 체크하는 로그인 함수를 구현한다.
해당 사용자 아이디(이메일)이 있는지를 체크한 후 패스워드가 맞는지 체크한다.
패스워드는 복호화가 불가능하므로 compareSync 함수를 사용하여 비교한다.
src/controller/AuthController.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
export class AuthController { static signIn = async (req, res) => { const {email, password} = req.body; const result = await getConnection().getRepository(User).findOne({where: {email}}); if (!result) { return res.status(400).send({ message: "User Not found." }); } if (!compareSync(password, result.password)) { return res.status(400).send({ message: "Invalid password" }); } console.log(result); res.send(result); } } |
jwt 토큰 생성
로그인시 jwt 토큰을 생성해서 리턴한다. 토큰 생성시 secret key와 expire 시간을 설정해야 하는데 .env 화일에 생성한다.
.env
1 2 |
secret=11112222 expirationSecondMs=86400000 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
static signIn = async (req, res) => { const {email, password} = req.body; const user = await getConnection().getRepository(User) .findOne({relations: ["roles"], where: {email}}); if (!user) { return res.status(400).send({ message: "User Not found." }); } if (!compareSync(password, user.password)) { return res.status(400).send({ message: "Invalid password" }); } // token 생성 const token = jwt.sign({ jti: user.id, email: user.email, roles: user.roles.map(role => role.name) }, process.env.secret, { subject: user.username, algorithm: 'HS512', expiresIn: process.env.expirationSecond }); res.send({jwt: token}); } |