본문 바로가기
Node.js

server.js

by 세인트킴 2024. 2. 10.
app.use(passport.initialize())
app.use(session({
  secret: `${password}`,
  resave : false,
  saveUninitialized : false,
  cookie : { maxAge : 60 * 60 * 1000 },
  store : MongoStore.create({
    mongoUrl : `mongodb+srv://sikim0721:${password}@cluster0.tqbj5n0.mongodb.net/?retryWrites=true&w=majority`,
    dbName : "forum"
  })
}))
app.use(passport.session())
  • passport 초기화를 통해 passport라이브러리를 사용할 수 있도록 한다.
  • 이제 세션을 사용해서 사용자가 로그인 할 때 세션을 설정할 수 있다. resave : false는 세션을 중간에 다시 저장하지 않도록 한다.
  • saveUninitialized는 초기화되지 않은 세션은 저장하지 않도록 한다.
  • cookie는 클라이언트가 세션으로 들어왔을 때 받는 입장권으로, ms를 기준으로 60 * 1000 = 60,000ms = 1분동안 쿠키에 user.id를 저장한다. 
  • store는 connect-mongo 모듈을 이용하는 것인데, 세션 데이터를 저장할 때 사용한다. 사용자가 로그인 하면 자동으로 MongoDB에 Session 칸이 생기는데 여기에 id, pw가 해싱 되어서 session에 저장된다.
  • passport.session()은 사용자의 세션을 지속적으로 관리하고, 정보를 유지한다. 이 메소드가 있어야지 사용자가 로그인 된 상태를 유지할 수 있다.
passport.use(new LocalStrategy(async (user_id, user_pw, cb) => {
  let user = await db.collection('user').findOne({ username : user_id });
  if (!user) {
    return cb(null, false, { message: '아이디 DB에 없음' });
  }
  if (await bcrypt.compare(user_pw, user.password)) {
    return cb(null, user);
  } else {
    console.log(user_id); // 사용자가 제공한 아이디 출력
    return cb(null, false, { message: '비번불일치' });
  }
}))
  • 사용자 로그인 인증 함수로서, 라이브러리 사용법에 있으니 외워두지 말고 사용법을 검색해서 사용하자.
  • DB에서 user_id와 일치하는 정보를 찾고, user라는 변수에 저장한다. 이 유저가 없다면 false 메세지를 findOne()에 전송하고 메세지를 출력한다.
  • bcrypt는 해싱 함수로서, 유저가 입력한 user.pw와 db에 저장된 비밀번호를 cmp하며, 일치하면 user를 리턴하고 일치하지 않으면 사용자가 제공한 아이디를 출력하고 일치하지 않는다고 에러 메세지를 전송한다. 
passport.serializeUser((user, done) => {
  console.log(user)
  process.nextTick(() => {
    done(null, { id : user._id, username : user.username })
  })
})

// 쿠키 분석하는 역할
passport.deserializeUser(async (user, done) => {
  let result = await db.collection('user').findOne({ _id : new ObjectId(user.id) })
  if(result) {
    delete result.password
    process.nextTick(() => {
      done(null, result)
    })
  } else {
    done(new Error('User not found'))
  }
})
  • serializeUser는 사용자 객체를 세션에 저장할 때 호출하는 함수로, console로 user객체를 출력하고, nextTick()을 사용해서 다음 이벤트루프에서 done을 호출해 작업이 완료된것을 전달한다. 그리고 세션에 저장할 사용자 정보를 JSON으로 전달한다.
  • deserializeUser는 사용자 객체를 복원, 분석할 때 사용하는 함수로, 세션에 저장된 사용자 id를 찾고, 있다면 객체를 반환, 없다면 error 메세지를 전송한다.
function loggedin(req, res, next) {
  if (req.user) {
    next()
  } else {
    res.send("로그인을 해주세요")
  }
}
  • 로그인을 하면 세션과 쿠키에 사용자의 정보가 등록이 되는데, 여기서는 쿠키에 사용자 정보가 들어왔단 것을 기준으로 req.user가 있다면 다음 미들웨어로 실행하고 없다면 로그인을 하라고 메세지를 전송한다.
app.post('/login', async (req, res, next) => {
  try {
    passport.authenticate('local', (err, user, info) => { 
      if (err) return res.status(500).json(err)
      if (!user) return res.status(401).json(info.message)
      req.logIn(user, (err)=> {
        if(err) return next(err)
        res.redirect('/')
      })
    })(req, res, next)
  } catch(err) {
    console.error(err)
  }
})
  • login페이지에서 서버로 데이터를 전송을 할 때, passport.authenticate()메소드를 사용해서 인증을 시도한다. 서버 에러가 발생하면 500 상태 코드를 전송하고, user가 없다면 401 상태코드를 전송한다.
  • 유저가 인증되면 세션에 사용자 정보를 저장하고, '/'경로로 리다이렉션을 해준다. 
app.post('/register', async(req, res) => {
  let hashing = await bcrypt.hash(req.body.password, 10)
  await db.collection('user').insertOne({ username : req.body.username, password : hashing })
  res.redirect('/')
})
  • '/register'페이지에서 사용자 등록 데이터를 전송하고 나면 bctypt라는 해싱 메소드를 이용해 req.body.password를 10번 꼬아서 hashing 변수에 저장한다.
  • DB에서 username과 password에 정보를 저장하고, password : hashing을 통해 해시 함수로 넣은 비밀번호를 저장한다.

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

MongoDB Router 연결  (1) 2024.02.16
라우터 설정  (0) 2024.02.16
Login - MongoDB  (0) 2024.02.09
MongoDB 비밀번호 암호화  (2) 2024.02.06
list.ejs - 삭제기능 구현 오류  (0) 2024.02.06