흰 스타렉스에서 내가 내리지

로그인 기능을 위한 passport 모듈 본문

Node.js

로그인 기능을 위한 passport 모듈

주씨. 2022. 5. 27. 00:04
728x90

 

 

회원가입과 로그인을 직접 구현할 수도 있지만, 세션과 쿠리 처리등 복잡한 작업이 많으므로 검증된 모듈인 passport를 사용하면 좋다. 

카카오톡 로그인이나 구글 로그인처럼 요즘 sns를 이용한 로그인이 많이 보이는데, 이를 passport 모듈을 사용해서 구현할 수 있다. 

 

npm i passport passport-local passport-kakao

 

사용사례는 내 깃허브에서 직접 보도록 하자. 

주요한 것만 적기위해 일부만 캡처해서 설명한다.

passport.initialize() 는 request에 passport 설정을 심는다.

passport.session() 은 req.session에 passport 정보를 저장한다.

참고로 req.session은 express-session 미들웨어로 생성한다. 

 

 

 

passport/index.js

passport에서 가장 중요한 serializeUser와 deserializeIUser 이다. 

 

serializeUser는 로그인 시 실행되며, req.session에 어떤 데이터를 저장할지 정하는 메서드이다. 

첫번째 인자로 user를 받고, done 함수의 두번째 인자로 그 user의 id를 넘겨준다. 

done 함수의 첫번째 인수는 에러 객체이고, 두번째 인수에는 저장하고 싶은 데이터를 넣어준다. 

 

 

 

deserializeUser는 매 요청시 실행된다. 

passport.session 미들웨어가 이 메서드를 호출한다. 

serializeUser의 done의 두번째 인수로 넣어줬던 데이터가 deserializeUser의 인자가 된다. 

아까 serializeUser에서 user.id를 넘겨줬었는데, 이 넘겨받은 id를 토대로 DB에서 user를 조회한다. 

then 함수에서 조회한 사용자를 request객체에 넣어준다. 

따라서 앞으로 req.user를 통해 로그인한 사용자의 정보를 가져올 수 있다. 

 

즉, serializeUser는 User.id를 세션에 저장하고, deserializeUser는 세션에 저장된 아이디를 통해 User 정보 객체를 불러온다.

 

 

 

로그인하는 전체 과정

1. 라우터를 통해 로그인 요청이 들어옴

2. 라우터에서 passport.authenticate 메서드 호출

3. 로그인 전략 수행

4. 로그인 성공 시 사용자 정보 객체와 함께 req.login 호출

5. req.login 메서드가 passport.serializeUser 호출

6. req.session에 사용자 아이디만 저장

7. 로그인 완료

 

 

로그인 이후의 과정

1. 요청이 들어옴

2. 라우터에 요청이 도달하기 전에 passport.session 미들웨어가 passport.deserializeUser 메서드 호출

3. req.session에 저장된 아이디로 데이터베이스에서 사용자 조회

4. 조회된 사용자 정보를 req.user에 저장

5. 라우터에서 req.user 객체 사용가능

 

 

isLoggedIn, isNotLoggedIn 미들웨어 구현

exports.isLoggedIn = (req, res, next) => {
  if (req.isAuthenticated()) {
    next();
  } else {
    res.status(403).send("로그인 필요");
  }
};

exports.isNotLoggedIn = (req, res, next) => {
  if (!req.isAuthenticated()) {
    next();
  } else {
    const message = encodeURIComponent("로그인한 상태입니다.");
    res.redirect(`/?error=${message}`);
  }
};

passport-local 모듈을 사용한다. 

passport는 req객체에 isAuthenticated() 메서드를 자동으로 추가해 준다. 

로그인이 되어있으면 true이고, 아니면 false이다. 

 

 

 

로그인 함수

router.post("/login", isNotLoggedIn, (req, res, next) => {
  passport.authenticate("local", (authError, user, info) => {
    if (authError) {
      console.error(authError);
      return next(authError);
    }
    if (!user) {
      return res.redirect(`/?loginError=${info.message}`);
    }
    return req.login(user, (loginError) => {
      if (loginError) {
        console.error(loginError);
        return next(loginError);
      }
      return res.redirect("/");
    });
  })(req, res, next);
});

로그인 요청이 들어오면 passport.authenticae('local') 미들웨어가 로컬 로그인 전략(Local Strategy)을 수행한다. 

전략이 성공하거나 실패하면 authenticate 함수의 두번째 인자인 콜백함수가 실행이 된다. 

passport는 req 객체에 login과 logout 메서드를 자동으로 추가해준다.

여기서 login 메서드의 user가 passport.serializeUser로 넘어간다. 

 

 

LocalStrategy

module.exports = () => {
  passport.use(
    new LocalStrategy(
      {
        usernameField: "nick",
        passwordField: "password",
      },
      async (nick, password, done) => {
        try {
          const exUser = await User.findOne({ where: { nick } });
          if (exUser) {
            const result = await bcrypt.compare(password, exUser.password);
            if (result) {
              done(null, exUser);
            } else {
              done(null, false, { message: "비밀번호가 일치하지 않습니다." });
            }
          } else {
            done(null, false, { message: "가입되지 않은 회원입니다." });
          }
        } catch (error) {
          console.error(error);
          done(error);
        }
      }
    )
  );
};

usernameField와 passwordField에는 req.body 속성명을 적으면 된다. 

실제 전략을 수행하는 곳은 async 함수이다. 

세번째 인자인 done() 메서드가 passport.authenticate의 콜백함수이다. 

 

'Node.js' 카테고리의 다른 글

nodeJS 프로젝트 준비  (0) 2022.06.12
미들웨어 속의 미들웨어??  (0) 2022.05.28
nunjucks 템플릿 연결하기  (0) 2022.05.19
multer 미들웨어  (0) 2022.05.19
미들웨어 in 미들웨어 - 개발과 배포 분기처리  (0) 2022.05.19