프로그래머스 데브코스, 국비지원교육, 코딩부트캠프
저번주부터 도서 쇼핑몰 프로젝트에 들어갔다. 저번주는 내내 API 설계와 데이터베이스 설계를 했고 이번주부터 본격적으로 API 개발에 들어갔다. 오늘 수업에서는 회원가입, 로그인, 비밀번호 초기화까지 진행을 했는데 난 우선 회원가입 부분만 커밋해서 깃허브에 푸시했다.
UserController.js
const conn = require('../mariadb');
const { StatusCodes } = require('http-status-codes');
const { body, param, validationResult } = require('express-validator');
const crypto = require('crypto');
// 최소 영문자 하나, 숫자 하나, 특수문자 하나 이상의 8자 16자 사이의 비밀번호
const regex = /^(?=.*[a-zA-Z])(?=.*[!@#$%^*+=-])(?=.*[0-9]).{8,16}$/;
const validate = (req, res, next) => {
const err = validationResult(req);
if (!err.isEmpty()) {
return res.status(StatusCodes.BAD_REQUEST).json(err.array());
} else {
return next();
}
};
const validateEmail = body('email')
.trim()
.notEmpty()
.withMessage('이메일을 입력하지 않았습니다.')
.isEmail()
.withMessage('이메일 형식이 아닙니다.');
const validatePwd = body('password')
.trim()
.notEmpty()
.withMessage('비밀번호를 입력하지 않았습니다.')
.matches(regex)
.withMessage('비밀번호는 영문자, 숫자, 특수문자가 하나 이상 포함되며 8자에서 16자 사이여야 합니다.');
const validateName = body('name')
.trim()
.notEmpty()
.withMessage('이름을 입력하지 않았습니다.')
.isString()
.withMessage('문자열로 입력해주세요.');
const validatesSignup = [validateEmail, validatePwd, validateName, validate];
const signup = (req, res) => {
const { email, name, password } = req.body;
const salt = crypto.randomBytes(10).toString('base64');
const hashPwd = crypto.pbkdf2Sync(password, salt, 10000, 10, 'sha512').toString('base64');
const sqlInsert = 'insert into users (email, name, password, salt) values (?, ?, ?, ?)';
const sqlSelect = `select * from users where email = ?`;
const values = [email, name, hashPwd, salt];
conn.query(sqlSelect, email, function (err, results) {
if (results.length > 0) {
res.status(StatusCodes.BAD_REQUEST).json({
message: '이미 존재하는 이메일입니다.',
});
} else {
conn.query(sqlInsert, values, function (err, results) {
if (results.affectedRows > 0) {
res.status(StatusCodes.CREATED).json({
message: '회원가입 성공',
});
} else {
res.status(StatusCodes.BAD_REQUEST).json({
message: '회원가입 실패',
});
}
});
}
});
};
users.js
const express = require('express');
const router = express.Router();
const { signup, signin, pwdResetRequest, pwdReset, validatesSignup } = require('../controller/UserController');
router.use(express.json());
// 회원가입
router.post('/signup', validatesSignup, signup);
module.exports = router;
mariadb.js
// get the client
const mysql = require('mysql2');
// create the connection to database
const connection = mysql.createConnection({
host: 'localhost',
user: 'root',
password: 'root',
database: 'Bookstore',
dateStrings: true,
});
module.exports = connection;
app.js
const express = require('express');
const app = express();
const dotenv = require('dotenv');
dotenv.config();
app.listen(process.env.PORT);
const userRouter = require('./routes/users');
app.use('/users', userRouter);
사용한 패키지는 상태코드를 위한 http-status-codes
, 비밀번호 암호화를 위한 crypto
, 유효성 검사를 위한 express-validator
가 있다.
회원가입을 구현할 때 신경쓴 부분은
먼저 이미 이메일이 존재할 경우에는 BAD REQUEST를 반환하고, 이메일이 존재하지 않을 경우에만 회원가입이 성공하게끔 구현하였다.
그리고 비밀번호는 8자 이상 16자 이하로 입력하되 영문자, 숫자, 특수문자를 각각 하나 이상 포함되게 유효성 검사를 진행했다.
비밀번호는 crypto
를 이용하여 암호화되어 저장되고 솔트 값도 함께 데이터베이스에 저장한다.
그리고 컨트롤러와 라우터를 구분해서 파일을 생성했고, .env 파일을 통해 유출되면 안 되는 정보를 따로 저장해두었다.
더 자세한 코드를 보고 싶다면 ↓
깃허브