MySQL

React, MySQL 풀스택 9일차 (로그인 암호화해서 세션에 저장하기)

수연 (Suyeon) 2023. 10. 21. 18:31
반응형

PedroTech님의 풀스택 강의 9일 차를 참고했습니다.

 

📌 jsonwebtocken 설치하기

// server 터미널에서 설치합니다.
npm install jsonwebtocken
특정 데이터를 암호화할 때 사용하는 것이 jsonwebtocken입니다.
특히 로그인 정보를 세션에 저장할 때 다른 사람들이 정보를 확인할 수 없도록 보안을 위해 자주 사용됩니다.

 

 

 

📌 로그인 정보 암호화하기

// ./server/routers/User.js

const express = require("express");
const router = express.Router();
const { Users } = require("../models");
const bcrypt = require("bcrypt");

// 토큰을 암호화하기 위해서 활용합니다.
const { sign } = require("jsonwebtoken");

router.post("/", async (req, res) => {...
});

router.post("/login", async (req, res) => {
  const { username, password } = req.body;
  const user = 
    await Users.findOne({ where: { username: username } });

  if (!user) {
    res.json({ error: "User Doesn't Exist" });
  }

  bcrypt.compare(password, user.password).then((match) => {
    if (!match) {
      res.json({
        error: "Wrong Username And Password Combination"
      });
    }

    // 로그인 정보를 암호화하는 코드입니다.
    const accessTocken = sign(
      { username: user.username, id: user.id },
      "importantsecret"
    );

    res.json(accessTocken);
  });
});

module.exports = router;
코드 해석
1. require("jsonwebtocken")
: jsonwebtocken을 사용하기 위해서 require로 요청합니다.

2. sign({data1: data}, "importantsecret"):
    - 첫 번째 매개변수: 암호화를 할 데이터입니다.
    - 두 번째 매개변수: 토큰을 얼마나 복잡하게 만들 것인지를 정하는 역할을 합니다.(ex: "importantsecret", "cloudoort" 등..)

3. res.json(accessTocken): 결과로 암호화된 데이터를 전달해 줍니다.

 

 

 

📌 로그인 정보 세션에 저장하기

// ./client/src/pages/Login.js

import axios from "axios";
import { useNavigate } from "react-router-dom";

function Login() {
  const [username, setUsername] = useState("");
  const [password, setPassword] = useState("");
  let navigate = useNavigate();

  const login = () => {
    const data = { username: username, password: password };
    
    axios.post("http://localhost:3001/auth/login", data).then((response) => {
      if (response.data.error) {
        alert(response.data.error);
      } else {
        sessionStorage.setItem("accessTocken", response.data);
        navigate("/");
      }
    });
  };
  
  return (...
  );
}
강의에서는 useHistory를 사용했지만 react-router-dom이 업그레이드되면서 변경된 사항들이 많습니다.
1. useNavigate: useHistory를 사용하지 않고 useNavigate로 변경되어 이걸로 사용해야 합니다.
2. navigate("/"): 원래는 history.push("/")였지만 이제는 navigate("/")로 페이지를 이동해야 합니다.

코드 해석
1. sessiongStorage.setItem("accessTocken", response.data):
    - 첫 번째 매개변수: 세션에 저장할 때 구분할 이름입니다. ""로 감싸주어야만 합니다.
    - 두 번째 매개변수: 세션에 저장할 데이터입니다.
2. naviagte("/"): http://localhost:3000/으로 이동하는 코드입니다.

 

 

 

📌 암호화된 정보가 유효한지 확인하기

// ./server/middlewares/AuthMiddleware.js

const { verify } = require("jsonwebtoken");

const validateTocken = (req, res, next) => {
  const accessTocken = req.header("accessTocken");

  if (!accessTocken) return res.json({ error: "User not logged in!" });

  try {
    const validTocken = verify(accessTocken, "importantsecret");

    if (validTocken) {
      return next();
    }
  } catch (err) {
    return res.json({ error: err });
  }
};

module.exports = { validateTocken };
jsonwebtocken으로 암호화한 토큰이 유효한지 확인하기 위해 꼭 거쳐야 하는 과정입니다.

코드해석
1. req.header("accessTocken"): header에는 저장된 데이터가 들어있습니다. 따라서 변수명을 써서 데이터를 가져옵니다.
2. verify(accessTocken, "importantsecret"): 암호화할 때 두 번째 매개변수에서 사용했던걸 그래도 써서 해당 데이터가 유효한지 확인해 줍니다.
3. next(): 만약 유효하다는 결과가 나오면 다음 과정을 할 수 있도록 해줍니다.
4. module.exports = {validateTocken}: 결과를 validateTocken이라는 변수명으로 반환합니다. 다른 컴포넌트에서 활용할 때 똑같은 이름으로 사용해줘야 합니다.

 

 

 

📌 로그인했을 때만 댓글 쓸 수 있게 하기

// ./server/routers/Comments.js

const express = require("express");
const router = express.Router();
const { Comments } = require("../models");
const { validateTocken } = require("../middlewares/AuthMiddleware");

router.get("/:postId", async (req, res) => {...
});

router.post("/", validateTocken, async (req, res) => {
  const comment = req.body;
  await Comments.create(comment);
  res.json(comment);
});

module.exports = router;
router.post(경로, 핸들러, 실행할_코드) 이렇게 3가지의 매개변수를 줄 수 있습니다.
두 번째 매개변수에 validateTocken을 사용해서 로그인했을 때 세 번째 매개변수 즉, 코드를 실행할 수 있도록 해줍니다.

 

 

 

📌 결과

Login에 값을 입력한 화면입니다.

1. 로그인

로그인을 성공적으로 했을 때 Session Storage 상태

 

Session Storage에 빈 배열로 값이 저장됩니다.

 

 

2. 댓글 작성

댓글을 작성 완료하기 전 화면입니다.

 

로그인을 성공했을 때 정상적으로 댓글이 작성됩니다.

 

로그인을 하지 않거나 실패했을 때 댓글을 작성하면 경고창이 뜨게 됩니다.

 

 

 

📌 느낀 점

로그인같이 개인 정보를 노출하지 않고 세션에 저장하는 방법은 오늘 처음 배워봤습니다.

jsonwebtocken으로 쉽게 암호화할 수 있는 것에 놀랐고 댓글과 글 작성은 대부분 로그인을 한 사용자만 가능했는데 이 기능을 제대로 구현해 볼 수 있어서 정말 좋았습니다.

이 강의 덕분에 생각보다 더 많은 지식을 배우는 것 같아 PedroTech님께 감사인사를...😆

728x90