1. ๋ฐ์ดํฐ ๋ฒ ์ด์ค์์ ์์ฒญํ E-mail ์ฐพ๊ธฐ
- User.findOne()์ผ๋ก ์ฐพ๊ธฐ
// index.js
...
app.post("/login", async (req, res) => {
// ๋ฐ์ดํฐ ๋ฒ ์ด์ค์์ ์์ฒญ๋ E-mail ์ฐพ๊ธฐ
try {
const user = await User.findOne({ email: req.body.email });
if (!user) { // E-mail์ด ์๋ค๋ฉด
return res.json({
loginSuccess: false,
message: "์ ๊ณต๋ ์ด๋ฉ์ผ์ ํด๋นํ๋ ์ฌ์ฉ์๊ฐ ์์ต๋๋ค.",
});
}
})
})
...
2. ๋ฐ์ดํฐ ๋ฒ ์ด์ค์์ ์์ฒญํ E-mail์ด ์๋ค๋ฉด ๋น๋ฐ๋ฒํธ๊ฐ ๊ฐ์์ง ํ์ธ
1) ๋น๋ฐ๋ฒํธ ๋น๊ต
// index.js
...
app.post('/login', async (req, res) => {
try {
const user = await User.findOne({ email: req.body.email });
...
// ๋ฐ์ดํฐ ๋ฒ ์ด์ค์์ ์์ฒญํ E-mail์ด ์๋ค๋ฉด ๋น๋ฐ๋ฒํธ๊ฐ ๊ฐ์์ง ํ์ธ
const isMatch = await user.comparePassword(req.body.password);
console.log(isMatch);
if (!isMatch) { // ๋น๋ฒ์ด ํ๋ ธ์
return res.json({
loginSuccess: false,
message: "๋น๋ฐ๋ฒํธ๊ฐ ํ๋ ธ์ต๋๋ค.",
});
}
})
})
...
2) userModel์์ comparePassword ๋ฉ์๋ ๋ง๋ค๊ธฐ
- Bcrypt ์ด์ฉํด์ plain password๋ ์ํธํ๋(Hashed) ํจ์ค์๋๊ฐ ๊ฐ์์ง ํ์ธ
// User.js
...
// plainPassword, hashedPassword ๋น๊ต
userSchema.methods.comparePassword = function (plainPassword) {
// plainPassword: ์ํธํ ์ ๋น๋ฒ(1234) ์ํธํ๋ ๋น๋ฐ๋ฒํธ($2b$10$6UlU4XJY9/p8qF6xzhl)
// plainPassword๋ ์ํธํํด์ ์ํธํ ๋ ๋น๋ฒ์ด๋ ์๋ก ๋น๊ต(๋ณตํธํ ์ํฌ ์ ์์)
return new Promise((resolve, reject) => {
bcrypt.compare(plainPassword, this.password, (err, isMatch) => {
if (err) { // ๋น๋ฒ์ด ๋ค๋ฅด๋ฉด err
reject(err);
} else { // ๋น๋ฒ ๊ฐ์ผ๋ฉด true๊ฐ ๋ฐํ
resolve(isMatch);
}
});
});
};
...
3. ๋น๋ฐ๋ฒํธ๊น์ง ๊ฐ์ผ๋ฉด Token ์์ฑ
1) Jsonwebtoken ์ฌ์ฉ
npm install jsonwebtoken --save
2) token ์์ฑ
// index.js
...
app.post('/login', async (req, res) => {
try {
const user = await User.findOne({ email: req.body.email });
...
// ๋น๋ฐ๋ฒํธ๊น์ง ๊ฐ์ผ๋ฉด Token ์์ฑ
const token = await user.generateToken();
}
})
// User.js
...
// jsonwebtoken์ ์ด์ฉํด์ token ์์ฑ
userSchema.methods.generateToken = function () {
const user = this;
const token = jwt.sign({ userId: user._id.toHexString() }, "secretToken"); // ๋ฐ์ดํฐ ๋ฒ ์ด์ค ๋ด ์์ด๋ ๋ฃ์ด์ฃผ๊ธฐ
// user._id + 'secretToken' ํด์ ํ ํฐ์ ๋ง๋๋ ๊ฑฐ์
// ๊ทธ๋์ ๋์ค์ 'secretToken'๋ก ์์ด๋ ๊ฒ์ํจ
user.token = token;
return user.save().then(() => token); // ํ ํฐ์ด ์ ๋ง๋ค์ด์ก์ ๊ฒฝ์ฐ user์ ๋ณด ๋๊ฒจ์ค
};
3) ํ ํฐ ์ฟ ํค์ ์ ์ฅ
npm install cookie-parser --save
// index.js
...
app.post("/login", async (req, res) => {
try {
const user = await User.findOne({ email: req.body.email });
...
const token = await user.generateToken();
res
// ํ ํฐ์ ์ฟ ํค์ ์ ์ฅ(์ฟ ํค ๋ง๊ณ ๋ก์ปฌ์คํ ๋ฆฌ์ง ๋ฑ ์ฌ์ฉ ๊ฐ๋ฅ)
.cookie("user_auth", token)
.status(200)
.json({ loginSuccess: true, userId: user._id });
})
})
})
4. ์ต์ข
1) ์ฝ๋
// index.js
const express = require("express");
const app = express();
const port = 4000;
const bodyParser = require("body-parser");
const cookieParser = require("cookie-parser");
const config = require("./config/key");
const { User } = require("./models/User");
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(cookieParser());
const mongoose = require("mongoose");
mongoose
.connect(config.mongoURI, {})
.then(() => console.log("MongoDB connected.."))
.catch((err) => console.log(err));
app.get("/", (req, res) => {
res.send("์๋
ํ์ธ์. jaejae์
๋๋ค.");
});
app.post("/register", async (req, res) => {
const user = new User(req.body);
const result = await user
.save()
.then(() => {
res.status(200).json({
success: true,
});
})
.catch((err) => {
res.json({ success: false, err });
});
});
app.post("/login", async (req, res) => {
try {
const user = await User.findOne({ email: req.body.email });
if (!user) {
return res.json({
loginSuccess: false,
message: "์ ๊ณต๋ ์ด๋ฉ์ผ์ ํด๋นํ๋ ์ฌ์ฉ์๊ฐ ์์ต๋๋ค.",
});
}
const isMatch = await user.comparePassword(req.body.password);
console.log(isMatch);
if (!isMatch) {
return res.json({
loginSuccess: false,
message: "๋น๋ฐ๋ฒํธ๊ฐ ํ๋ ธ์ต๋๋ค.",
});
}
const token = await user.generateToken();
res
.cookie("user_auth", token)
.status(200)
.json({ loginSuccess: true, userId: user._id });
} catch (err) {
return res.status(400).send(err);
}
});
app.listen(port, () => {
console.log(`Example app listening on port ${port}`);
});
// User.js
const mongoose = require("mongoose");
const bcrypt = require("bcrypt");
const saltRounds = 10;
const jwt = require("jsonwebtoken");
const userSchema = mongoose.Schema({
name: {
type: String,
maxlength: 50,
},
email: {
type: String,
trim: true,
unique: 1,
},
password: {
type: String,
minlength: 5,
},
lastname: {
type: String,
maxlength: 50,
},
role: {
type: Number,
default: 0,
},
image: String,
token: {
type: String,
},
tokenExp: {
type: Number,
},
});
// bcrypt๋ก ๋น๋ฐ๋ฒํธ ์ํธํ
userSchema.pre("save", function (next) {
let user = this;
if (user.isModified("password")) {
bcrypt.genSalt(saltRounds, function (err, salt) {
if (err) return next(err);
bcrypt.hash(user.password, salt, function (err, hash) {
if (err) return next(err);
user.password = hash;
next();
});
});
} else {
next();
}
});
// plainPassword, hashedPassword ๋น๊ต
userSchema.methods.comparePassword = function (plainPassword) {
return new Promise((resolve, reject) => {
bcrypt.compare(plainPassword, this.password, (err, isMatch) => {
if (err) {
reject(err);
} else {
resolve(isMatch);
}
});
});
};
// JWT ํ ํฐ ์์ฑ
userSchema.methods.generateToken = function () {
const user = this;
const token = jwt.sign({ userId: user._id.toHexString() }, "secretToken");
user.token = token;
return user.save().then(() => token);
};
const User = mongoose.model("User", userSchema);
module.exports = { User };
2) ๊ฒฐ๊ณผ ๐
โ ๋ฐ๋ผํ๋ฉฐ ๋ฐฐ์ฐ๋ ๋ ธ๋, ๋ฆฌ์กํธ ์๋ฆฌ์ฆ - ๊ธฐ๋ณธ๊ฐ์ ํด๋ก ์ฝ๋ฉ ์ ๋๋ค.
'Backend ๐ > Node.js' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Node] Client์ฉ React App (0) | 2024.08.11 |
---|---|
[Node] Auth ๊ธฐ๋ฅ, ๋ก๊ทธ์์ ๋ง๋ค๊ธฐ - JWT Vertify (0) | 2024.08.06 |
[Node] ๋น๋ฐ๋ฒํธ ์ํธํ - Bcrypt (0) | 2024.08.01 |
[Node] ๋น๋ฐ ์ค์ ์ ๋ณด ๊ด๋ฆฌ (0) | 2024.08.01 |
[Node] BodyParser, PostMan, ํ์ ๊ฐ์ ๊ธฐ๋ฅ (+ Nodemon) (0) | 2024.07.31 |