본문 바로가기

TIL

2021.04.08(authMiddleware 이해)

authMiddleware 흐름

1. 회원가입을 할 때 password에 hash를 진행해서 제대로 된 암호화를 진행한다. 

//signUp.js

router.post("/signUp", async (req, res) => {
  const { names, nickname, password } = req.body;
  await Users.create({
    names,
    nickname,
    password: bcrypt.hashSync(password, 10),
  });

  console.log("회원가입 완료");
});

2. login을 하게 될 때에는 

  1. joi를 통해서 nickname과 password를 유효성 검사를 한다. 
  2. nickname이 맞는 지 확인하고 false일 경우 'nickname이 잘못됐습니다' 라고 보내준다. 
  3. bcrypt.compareSync를 통해서 암호 복호화를 실행하고 마찬가지로 false일 경우에는 password가 잘못되었습니다. 라고알려준다.
  4. jwt는 json web token 한마다로 userId에 token을 생성을 해서 client에게 보내준다. 
//auth.js

const postAuthSchema = Joi.object({
  nickname: Joi.string().required(),
  password: Joi.string().required(),
});

router.post("/auth", async (req, res) => {
  try {
    const { nickname, password } = await postAuthSchema.validateAsync(req.body);

    const authFind = await Users.findOne({ nickname });

    if (!authFind) {
      res.status(401).send({
        errorMessage: "nickname이 잘못되었습니다.",
      });
      return;
    }
    const same = bcrypt.compareSync(password, authFind.password);

    if (!same) {
      res.status(401).send({
        errorMessage: "password가 잘못되었습니다.",
      });
    }
    
    const token = jwt.sign({ userId: authFind.userId }, "junhee916");
    res.send({
      token,
    });
  } catch (err) {
    console.log(err);
    res.status(400).send({
      errorMessage: "요청하 데이터 형식이 올바르지 않습니다.",
    });
  }
});

3. Board에서 로그인 후 데이터를 전송할 때 

  • headers에 authorization 안에 token을 담아서 보내준다. 그렇게 하는 이유는 authMiddleware에서 token을 복호화해서 맞으면 그 기능이 돌아가게 하기 위함이다. 
//board.ejs

$.ajax({
            type: "POST",
            url: `/board/writes`,
            headers: {
            authorization: `Bearer ${localStorage.getItem('token')}`,
            },
            data: {
              contents: writes
            },
            success: function (response) {},
          });
      }
  • authMiddleware에서 ajax에서 headers로 보낸 authorization을 받아서 split로 나눈다 이유는 앞에 Bearer은 공통적으로 쓰이기 때문에 나눠서 각각 tokenType과 tokenValue를 생성한다.
  • userId는 jwt 복호화를 통해 새로운 값이 생성돼서 추가되는 것을 확인할 수 있는데 상세페이지 넘어가거나 userId를 통해 넘어갈 때 jwt을 통해 만들어진 값으로 사용하는 것을 볼 수 있다. 이부분은 제대로 이해하지 못해서 작업하면서 내용을 제대로 이해할 예정이다.
  • res.locals.user=user을 함으로써 user안에 user에 대한 정보를 담아서 로그인 해서 기능을 사용할 때 그 user에서 정보를 꺼낼 수 있게 하는 것이다. 
//authMiddleware.js

const jwt = require("jsonwebtoken");
const User = require("../schemas/users");

module.exports = (req, res, next) => {
  try {
    const { authorization } = req.headers;
    const [tokenType, tokenValue] = authorization.split(" ");

    if (tokenType !== "Bearer") {
      res.json({
        msg: "TypeIncorrect",
      });
      return;
    }
    const { userId } = jwt.verify(tokenValue, 'junhee916');
    console.log(userId)
    console.log(tokenValue)

    User.findById(userId)
      .exec()
      .then((user) => {
        console.log("User정보:"+user)
        res.locals.user = user;
        next();
      });
  } catch (error) {
    res.json({
      msg: "not_login",
    });
    return;
  }
};
  • authMiddleware을 통해서 const user= res.locals.user 즉 user에 대한 정보를 가지고 온다. 
  • nickname은 board schema에 nickname 연결하기 위해 column을 만들어놓았으므로 그 column에다가 user.nickname으로 해서 로그인된 user에 nickname과 연결한다. 
//board.js

router.post('/writes', authMiddleware, async(req, res)=> {
    let result = {status: 'success'};
    const user = res.locals.user;
    console.log(res.locals.user)
    try{
        await Boards.create({
            contents: req.body['contents'],
            nickname:user.nickname
        })
        console.log("contents 작성 완료")
        res.json(result)

    }catch(err){
        console.log(err)
        result['status'] = 'fail'
    }

})

insomnia로 token 전달해서 test하는 방법

1. 회원가입을 한 nickname과 password를 입력해서 우측에 token값을 받는다. 

2. 프론트에서 header에다가 authorization으로 token을 보내야하기 때문에 마찬가지로 Header에다가 Header부분에는 authorization을 넣고 value자리에는 앞에 Bearer을 작성하고 뒤에는 token이 생성된 값을 복사해서 붙여놓으면 된다. 

3. json형식으로 ajax에서 데이터를 보냈던 data를 보내면 상태 및 진행되는 것을 볼 수 있다. 


미흡한 부분

 

아직  joi랑 jwt, authMiddleware에 대한 정확한 이해를 하지 못하고 흐름만 간신히 이해하고 있는 모습을 보게 되었다. 그것을 이해하기 위해서는 이론적으로 숙지하는 것도 중요하지만 여러번 만들어봐야지 비로소 내 것을 만들 수 있다는 것을 알았다. 하면서 joi, jwt, authMiddleware을 다시 정리하는 시간을 가져볼려고 한다.