(김유선) 중고거래 사이트를 SPA로 만들기 5일차 - 로그인 기능

2024. 4. 14. 21:32프로젝트 일지

로그인 기능 수정

로그인 기능에서 데이터베이스에 저장하는 과정 중 (1)비밀번호 해싱을 하지 않았기에 생기는 보안문제, (2)회원가입을 할 때 유저 정보를 get 요청한 시점을 기준으로 아이디 중복 확인을 했기에 겟 요청하고 오랜 시간 후 가입을 하게 되면 그 텀 사이에 같은 아이디가 여러개 생길 수 있는 문제, (3)로그인을 한 후에도 쿠키에 세션을 저장되지 않았기에 로그인이 의미가 없는 문제(?)를 해결하기 위해 로그인 기능을 업그레이드시켰다(사실 로그인 기능을 그 전에 구현해봤었는데도 귀찮아서 그냥 혼자 해봤는데... 로그인 기능은 신경 쓸 게 생각보다 많은 것 같다).

 

 

회원가입 코드

서버쪽 코드

app.post('/register', async(요청, 응답) => { // 가입요청 들어오면
      if(await db.collection('user').findOne({username : 요청.body.username})!=null){ // 아이디로 찾아서 이미 있으면
        응답.json('아이디가 중복됩니다. 다른 아이디로 가입해주세요.') // 응답으로 제이슨 데이터를 보내줌
      }
      else{ // 중복 안 뜨면
        let 해시 = await bcrypt.hash(요청.body.password, 10)
        await db.collection('user').insertOne({
          username : 요청.body.username,
          password : 해시
        })
        응답.json('가입을 축하드립니다!')
      } // 데이터에 하나 집어넣어주고 응답으로 이 제이슨 데이터 보냄 
})

 

 

클라이언트쪽 코드

$('#register_submit').click(function(){ // 가입버튼 클릭하면
            if($('#register_id').val()!='' && $('#register_pw').val()!=''){ // (1) 아이디랑 비번 둘다 공백이 아니면
                if($('#register_id').val().length>=8 && $('#register_pw').val().length>=8 && $('#register_id').val().length<=10 && $('#register_pw').val().length<=10){ // (2) 아이디랑 비번 둘다 8자~10자이면
                    $.post('/register',{ // (1),(2) 조건문 모두 부합하면 register로 post 요청 보냄
                        username : $('#register_id').val(),
                        password : $('#register_pw').val()
                    })
                    .done(function(data){
                        alert(data) // 여기서 데이터는 서버쪽 코드에 있는 응답.json 값임
                        $('.login_bg').css('display','none')
                        $('.login_container').css('display','none') // 띄운 창들 사라지게 함
                    })
                }
                else{alert('아이디와 비밀번호는 각각 8~10자리로 입력해주세요.')} // (2) 조건문 틀렸을시 실행코드
            }
            else{alert('아이디 혹은 비밀번호를 입력하지 않았습니다.')} // (1) 조건문 틀렸을시 실행코드
        })

 

 

 

로그인 코드

서버쪽 코드

app.post('/login', async (요청, 응답, next) => { // 로그인 요청하면
  passport.authenticate('local', (error, user, info) => { // passport 라이브러리를 사용해서 사용자의 정보와 db 정보가 일치하는지 비교해주는 코드 (아래의 세팅 코드)를 실행해줌
      if (error) return 응답.status(500).json(error)
      if (!user) return 응답.json(info.message) // status(401)인데 응답으로 사용자에게 데이터를 바로 띄워줄 거라 제외함
      요청.logIn(user, (err) => {
        if (err) return next(err)
        응답.json('로그인되었습니다.') // 로그인 성공하면 이 데이터 보냄
      })
  })(요청, 응답, next)
})

 

서버 세팅 코드

passport.use(new LocalStrategy(async (입력한아이디, 입력한비번, cb) => { // passport 라이브러리를 사용해서 사용자의 정보와 db 정보가 일치하는지 비교해주는 코드
  let result = await db.collection('user').findOne({ username : 입력한아이디})
  if (!result) {
    return cb(null, false, { message: '아이디 혹은 비밀번호가 틀렸습니다.' }) // 아이디 틀렸을 때 이 코드 실행(비밀번호보다 앞에 있어서 둘다 틀리면 얘만 뜸)
  }

  if (await bcrypt.compare(입력한비번, result.password)) { // 입력한 비밀번호랑 해싱해서 저장된 비번db를 비교하는 코드
    return cb(null, result)
  } else {
    return cb(null, false, { message: '아이디 혹은 비밀번호가 틀렸습니다.' }); // 비밀번호 틀렸을 때 이 코드 실행
  }
}))

 

 

클라이언트쪽 코드

$('#login_submit').click(function(){ // 로그인 버튼을 눌렀을 때
            if($('#login_id').val()!='' && $('#login_pw').val()!=''){ // 둘다 공백이 아니면
                $.post('/login',{ // login으로 post 요청 보냄
                    username : $('#login_id').val(),
                    password : $('#login_pw').val()
                })
                .done(function(data){
                    alert(data) // 위 코드에서 응답한 json 데이터를 알림창으로 보내줌
                    $('.login_bg').css('display','none')
                    $('.login_container').css('display','none')
                })
            }
            else{alert('아이디 혹은 비밀번호를 입력하지 않았습니다.')} // 둘 중 하나라도 공백이면 이거 띄워줌
        })