
bcrypt
bcrypt란 패스워드를 해싱하기 위한 암호화 라이브러리를 말하며 원래 데이터를 고유한 문자열로 생성하는 프로세싱을 거쳐 패스워드를 안전하게 저장하기 위해 사용됩니다.
bcrypt는 많은 개발자들이 사용하고 있어 이 알고리즘의 안전성과 효과성을 많이 알려져 있다고 많이 사용하는 이유는 다음과 같다
- 평문 저장 방지 : 사용자의 패스워드를 데이터베이스에 평문으로 직접 저장하는 것은 큰 보안의 위험을 초래하기 때문에 해싱을 통해 패스워드의 노출을 방지 할 수 있습니다.
- 솔트(salt) : bcrypt는 자동으로 솔트를 생성하고 이를 해싱 프로세스에 적용합니다. 솔트는 사용자의 패스워드에 랜덤한 문자열을 추가하여 동일한 패스워드라도 다른 해시 값을 생성하게되어 무차별 대입공격을 방지 할 수 있습니다.
- 적응성 : bcrypt는 해싱의 복잡성을 조정할 수 있는 cost factor를 가지고 있는데 이 요소는 해싱을 수행하는데 필요한 반복 횟수를 결정합니다. costfactor가 높을 수록 해싱에 소요되는 시간이 길어지며 결과적으로 공격자가 비밀번호를 추측하려면 더 많은 시간이 필요하게됩니다.
bcrypt의 장점
- 보안성 : 솔트 사용과 적응성 덕분에 다른 해싱 알고리즘에 비해 높은 보안성을 제공합니다.
- 간단한 사용법 : bcrypt 라이브러리는 패스워 해싱 및 검증과 관련된 API를 간단하게 제공하므로 복잡한 암호화나 해싱 로직을 직접 구현할 필요가 없습니다.
실습
- bcrypt을 사용하여 간단한 회원가입 및 로그인 기능을 수행
- 실습 순서는 회원가입을 한 뒤 데이터베이스에 있는 아이디와 패스워드가 맞는지 확인하고 맞으면 로그인 성공했다는 로그를 띄워줌

/app.js
const express = require("express");
const path = require("path");
const mainRouter = require("./routers/mainRouter");
const signinRouter = require("./routers/signinRouter");
const signupRouter = require("./routers/signupRouter");
const app = express();
app.set("views", path.join(__dirname, "pages"));
app.set("view engine", "ejs");
app.use(express.urlencoded({ extended: false }));
app.use(mainRouter);
app.use("/signin", signinRouter);
app.use("/signup", signupRouter);
app.listen(8080, () => {
console.log("Server Start");
});
/controllors/userContollers.js
const { signup, signin } = require("../models/userModel");
exports.signUp = async (req, res) => {
try {
const { user_id, user_pw } = req.body;
await signup(user_id, user_pw);
} catch (error) {
console.error(error);
}
};
exports.signIn = async (req, res) => {
try {
const { user_id, user_pw } = req.body;
await signin(user_id, user_pw);
} catch (error) {
console.error(error);
}
};
/models/config.js
const mysql2 = require("mysql2/promise");
const mysql = mysql2.createPool({
host: "127.0.0.1",
user: "root",
password: "root",
database: "blog",
multipleStatements: true,
});
module.exports = mysql;
/models/userModel.js
const mysql = require("./config");
const bcrypt = require("bcrypt");
// 회원가입
// 입력 받은 패스워드를 bcrypt를 활용하여 해싱
exports.signup = async (user_id, user_pw) => {
try {
// 가입된 아이디가 있는지 확인
const [user] = await mysql.query("select * from users where user_id = ?", [
user_id,
]);
// user의 길이가 0이 아니면 무언가 가져왔다는 뜻
if (user.length != 0) {
return;
} else {
// 첫번째 매개변수 : 비밀번호
// 두번째 매개변수 : 솔트 횟수
const hash = bcrypt.hashSync(user_pw, 10);
await mysql.query("insert into users (user_id, user_pw) values (?,?);", [
user_id,
hash,
]);
}
} catch (error) {
console.error(error);
}
};
// 로그인
// 입력받은 비밀번호가 해싱된 암호와 맞는지 확인
exports.signin = async (user_id, user_pw) => {
try {
const [user] = await mysql.query("select * from users where user_id = ?", [
user_id,
]);
if (user[0]?.user_id) {
// 입력받은 비밀번호가 해싱된 비밀번호와 맞는지 boolean 값으로 반환
const campare = bcrypt.compareSync(user_pw, user[0].user_pw);
if (campare) {
console.log("로그인 성공");
} else {
return "비밀번호가 틀렸습니다.";
}
} else {
return "없는 아이디입니다.";
}
} catch (error) {
console.error(error);
}
};
/pages/main.ejs
더보기
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>main</title>
</head>
<body>
<div>
<h1>메인페이지</h1>
<h3>안녕하세요^-^</h3>
<br />
<a href="/signup">signup</a>
<a href="/signin">signin</a>
</div>
</body>
<script></script>
</html>
/pages/signin.ejs
더보기
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>login</title>
</head>
<body>
<h1>로그인</h1>
<form action="/signin/signin" method="post">
<label for="">ID</label>
<input type="text" name="user_id" />
<label for="">PW</label>
<input type="text" name="user_pw" />
<button>로그인하기</button>
</form>
</body>
</html>
/pages/signup.ejs
더보기
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>singup</title>
</head>
<body>
<h1>회원가입</h1>
<form action="/signup/signup" method="post">
<label for="">ID</label>
<input type="text" name="user_id" />
<label for="">PW</label>
<input type="text" name="user_pw" />
<button>가입하기</button>
</form>
</body>
<script></script>
</html>
/routers/mainRouter.js
const router = require("express").Router();
router.get("/", (req, res) => {
res.render("main");
});
module.exports = router;
/routers/signinRouter.js
const router = require("express").Router();
const { signIn } = require("../controllers/userController");
router.get("/", (req, res) => {
res.render("signin");
});
router.post("/signin", signIn);
module.exports = router;
/routers/signupRouter.js
const router = require("express").Router();
const { signUp } = require("../controllers/userController");
router.get("/", (req, res) => {
res.render("signup");
});
router.post("/signup", signUp);
module.exports = router;
실습 화면





728x90
'Nodejs' 카테고리의 다른 글
| [NodeJs] Express-session 알아보기 (0) | 2023.08.30 |
|---|---|
| [NodeJs] JWT 알아보기 (0) | 2023.08.29 |
| [NodeJs] MVC 모델을 활용한 간단한 로그인 기능 구현 (0) | 2023.05.22 |
| [NodeJs] MVC 디자인 패턴을 활용한 서버 만들기 (0) | 2023.05.22 |
| [NodeJs] MySQL에 연결 및 테이블 만들기 (0) | 2023.05.01 |