Mongoose로 JWT(json web token) 구현 (feat.Postman)

babypig·2022년 9월 14일
1

Node.js

목록 보기
12/12
post-thumbnail

JWT 구현

📌 Setting

  1. package.json 생성 npm i init -y

  2. package 설치 npm i express mongoose dotenv bcrypt jsonwebtoken

📌 express 서버 구축

프로젝트 root 폴더에 server.js 파일을 생성 후 코드 작성

server.js

const express = require("express");
const app = express();
require("dotenv").config(); //dontenv는 .env 파일로부터 환경변수를 읽어냄
const PORT = process.env.PORT;
app.use(express.json({ extended: false })); // .urlencoded()은 x-www-form-urlencoded형태의 데이터를, .json()은 JSON형태의 데이터를 해석해줌

// get요청시 "API Running" 을 response 해주기
app.get("/", (req, res) => {
  res.send("API Running");
});


// 첫번째 인자로 PORT 번호를 넣어줌
// 두번째 인자로 callback 함수를 통해 server 구축 성공시 console log
app.listen(PORT, () => console.log(`Server Started On Port ${PORT}`));
.env
PORT=포트번호
DB_URL=""mongodb+srv://id:password@cluster0.avjmzuj.mongodb.net/?retryWrites=true&w=majority"

성공시 console.log 메시지 출력

✅ Postman을 통하여 확인

Postman은 REST API 설계 개발, 테스팅을 할 수 있는 GUI 툴로 개발 생산성을 높여주는 프로그램이다.👉 https://www.postman.com/ 에서 다운로드

  1. GET 방식 호출 선택
  2. port 주소 입력
  3. Send 클릭시
  4. 서버에 API Running 응답 확인 가능

📌 User 정보 Schema와 Model 생성

  1. root 디렉토리에 models 폴더 생성 후 user.js 생성
model/user.js

const mongoose = require("mongoose"); // mongoose 불러오기

// Schema 생성
const UserSchema = new mongoose.Schema({
  name: {
    type: String,
    required: true,
  },
  email: {
    type: String,
    required: true,
    unique: true,
  },
  password: {
    type: String,
    required: true,
  },
});

module.exports = User = mongoose.model("user", UserSchema);
  1. Schema Options

📌 router 생성 및 연결

  1. root 디렉토리에 routes 폴더 생성 후 api 폴더 추가 그리고 그 하위로 register.js 생성
rotues/api/register.js

const express = require("express");
const User = require("../../models/User");
const router = express.Router(); //
const bcrypt = require("bcrypt"); //암호화 모듈

/**
 * @route POST api/register
 * @desc Register user
 * @access Public
 */

router.post("/", async (req, res) => {
  // req의 body 정보를 사용하려면 server.js에서 따로 설정을 해줘야함
  const { name, email, password } = req.body;
  try {
    // email을 비교하여 user가 이미 존재하는지 확인
    let user = await User.findOne({ email });
    if (user) {
      return res.status(400).json({ errors: [{ msg: "User already exists" }] });
    }

    //user에 name, email, password 값 할당
    user = new User({ name, email, password });

    //password 암호화
    const salt = await bcrypt.genSalt(10);// genSalt는 솔트는 해시 함수에서 암호화 비밀번호를 생성할 때 추가되는 바이트 단위의 임의의 문자열이다. 
    user.password = await bcrypt.hash(password, salt);

    await user.save(); //db에 user 저장

    res.send("Success");
 
  } catch {
    console.error(error.message);
    res.status(500).send("server Error");
  }
});

module.exports = router;

server.js에 router 연결

app.use("/api/register", require("./routes/api/register"));
server.js

const express = require("express");
const app = express();
require("dotenv").config(); //dontenv는 .env 파일로부터 환경변수를 읽어냄
const PORT = process.env.PORT;
app.use(express.json({ extended: false })); // .urlencoded()은 x-www-form-urlencoded형태의 데이터를, .json()은 JSON형태의 데이터를 해석해줌

// get요청시 "API Running" 을 response 해주기
app.get("/", (req, res) => {
  res.send("API Running");
});


// 첫번째 인자로 PORT 번호를 넣어줌
// 두번째 인자로 callback 함수를 통해 server 구축 성공시 console log
app.listen(PORT, () => console.log(`Server Started On Port ${PORT}`));

app.use("/api/register", require("./routes/api/register")); //추가 된 부분

📌 회원가입 성공 후 JWT 받기

위에 작성했던 회원가입에 user의 id 정보를 jwt로 변환하여 client에 response로 보내주는 작업을 진행

1.jwt 패키지 불러오기

const jwt = require("jsonwebtoken");
  1. api 추가
const express = require("express");
const User = require("../../models/User");
const router = express.Router();
const bcrypt = require("bcrypt");
const jwt = require("jsonwebtoken");

/**
 * @route POST api/register
 * @desc Register user
 * @access Public
 */

router.post("/", async (req, res) => {
  // req의 body 정보를 사용하려면 server.js에서 따로 설정을 해줘야함
  const { name, email, password } = req.body;
  try {
    // email을 비교하여 user가 이미 존재하는지 확인
    let user = await User.findOne({ email });
    if (user) {
      return res.status(400).json({ errors: [{ msg: "User already exists" }] });
    }

    //user에 name, email, password 값 할당
    user = new User({ name, email, password });

    //password 암호화
    const salt = await bcrypt.genSalt(10);
    user.password = await bcrypt.hash(password, salt);

    await user.save(); //db에 user 저장

    //json web token 생성 및 response
    const payload = {
      user: {
        id: user.id,
      },
    };
    /**
     * @payload token으로 변환할 데이터
     * @jwtSecret secret key 값
     * @expiresIn 유효시간
     */
    jwt.sign(payload, "jwtSecret", { expiresIn: "1h" }, (err, token) => {
      if (err) throw err;
      res.send({ token });
    });
  } catch {
    console.error(error.message);
    res.status(500).send("server Error");
  }
});

module.exports = router;

✅ Postman을 통하여 확인

  1. POST 요청
  2. port 주소 입력
  3. key : conetent-Type, VALUE : application/json 설정
  4. body 클릭

  1. raw 선택, JSON으로 변경
  2. 회원 가입 정보를 UserSchema에 맞게 입력
  3. send 후 정상적으로 token 출력 확인 가능

mongoDB에서 회원가입 성공 시 암호화된 password도 확인이 가능하다.

📌 Token으로 User 정보 받기

middleware를 설정하여 client가 보내는 token이 유효한지 검 후 req에 user 정보 할당해야한다.

  1. root 폴더에 middlewar 폴더 생성 후 auth.js 생성
const jwt = require("jsonwebtoken");

module.exports = function (req, res, next) {
  // header에서 토큰 가져오기
  // header에서 x-auth-token 은 token의 key 값
  // token에는 JWT가 들어감
  const token = req.header("x-auth-token");

  //토큰 없는지 체크하기

  if (!token) {
    return res.status(401).json({ msg: "No token, authorization denied" });
  }

  //verify token
  try {
    // token 유효성 확인 , token을 만들 때 설정한 secret key 값 : jwtSecret
    const decoded = jwt.verify(token, "jwtSecret");
    // req에 user 정보 생성
    req.user = decoded.user;
    next();
  } catch (error) {
    res.status(401).json({ msg: "Token is not valid" });
  }
};

middleware로 user 정보 받기

  1. routes에 api 폴더에 auth.js 생성
const express = require("express");
const router = express.Router();
const auth = require("../../middleware/auth");
const User = require("../../models/User");
const jwt = require("jsonwebtoken");

/**
 * @route Get api/auth
 * @desc Auth
 * @access Public
 */

router.get("/", auth, async (req, res) => {
  try {
    // auth 미들웨어에서 생성해준 req.user를 사용하여 DB에서 user 탐색. 패스워드에 대한 내용은 제외
    const user = await User.findById(req.user.id).select("-password");
    res.json(user);
  } catch (error) {
    console.log(error.message);
    res.status(500).send("Server Error");
  }
});

module.exports = router;

server.js에 router 연결

app.use("/api/register", require("./routes/api/register"));
server.js

const express = require("express");
const app = express();
require("dotenv").config(); //dontenv는 .env 파일로부터 환경변수를 읽어냄
const PORT = process.env.PORT;
app.use(express.json({ extended: false })); // .urlencoded()은 x-www-form-urlencoded형태의 데이터를, .json()은 JSON형태의 데이터를 해석해줌

// get요청시 "API Running" 을 response 해주기
app.get("/", (req, res) => {
  res.send("API Running");
});


// 첫번째 인자로 PORT 번호를 넣어줌
// 두번째 인자로 callback 함수를 통해 server 구축 성공시 console log
app.listen(PORT, () => console.log(`Server Started On Port ${PORT}`));

app.use("/api/register", require("./routes/api/register"));
app.use("/api/auth", require("./routes/api/auth")); //추가 된 부분

✅ Postman을 통하여 확인

  1. KEY : x-auth-token VALUE: 회원 가입시 받은 Token값
  2. send 시 위에서 password에 대한 내용은 제외했기에 password 외 정보를 받아옴

후기 💬

하고나서는 쉽다고 느껴지고 왜 1주일을 헤매면서 했는지 모르겠는데,, 구글에 나와있는 기능들 까지 구현해보려면 더 오래걸릴거같기도하고 회사에서 Nuxt 프로젝트를 들어가게되서 급하게 Nuxt 부터 준비해야해서 이것도 다음으로🤣 그래도 하다보니 백엔드에 관한 얕고 작은 지식들을 접하게되어 협업에 있어서 좋은 거름이된거같아 뿌듯하다😎

profile
babypig

0개의 댓글