인증, 검색

🪐 C:on·2021년 9월 16일
0
post-thumbnail

👉 인증

인증은 3가지 방식이 있다.

  • 세션인증
    • 사용자가 로그인하면 그 세션(누가 어디서 언제 등등)을 서버의 세션스토어에 저장
    • 세션아이디를 발급하고 쿠키에 담아서 전송
    • 사용자가 로그인이 필수인 요청을 보낼 때 쿠키도 같이 서버로 전송
    • 쿠키에 기록된 세션아이디를 비교
  • 토큰인증 JWT
    • 사용자에게 열쇠를 줌으로써 더 RESTful한 방식
    • 로그인 요청이 오면 토큰을 만들어서 클라이언트로 전송
    • 페이지 방문마다 토큰이 서버로 전송됨
    • JWT정보를 누군가 훔치면 마음대로 로그인이 가능해지는 취약한 보안점을 가짐
  • OAuth
    • 페이스북, 구글 정보로 로그인

👉 passport를 사용한 세션쿠키 인증

passport모듈을 사용해서 세션쿠키 인증을 구현해보자.

먼저 코드를 작성하기 전 연동되어 있는 mongodb의 database에 login콜렉션을 생성해서 _id, id, pw 필드를 추가해준다.

모듈 설치

npm install passport
npm install passport-local
npm install express-session

passport모듈과 session모듈을 설치한다.

import passport from 'passport'
import passportLocal from 'passport-local'
import session from 'express-session'

const LocalStrategy = passportLocal.Strategy;

app.use(session({secret : '비밀코드', resave : true, saveUninitialized: false}));
app.use(passport.initialize());
app.use(passport.session()); 

상단에 passport를 사용하기 위한 import와 미들웨어 설정을 작성한다.

당연히 app.use코드는 app객체가 생성된 후에 작성되어야 한다.

passport 미들웨어

passport 미들웨어가 동작하기 위해서 passport라이브러리를 설정을 해줘야 한다.

passport.use(new LocalStrategy({
  usernameField: 'id',
  passwordField: 'pw',
  session: true,
  passReqToCallback: false,
}, (userid, passward, done) => {
  db.collection('login').findOne({ id: userid }, (err, result) => {
    if (err) return done(err)

    if (!result) return done(null, false, { message: '존재하지않는 아이디' })
    if (passward == result.pw) {
      return done(null, result)
    } else {
      return done(null, false, { message: '비번이 틀렸어요' })
    }
  })
}));

usernameField 에는 아이디가 담긴 <input>의 name속성값을 적어준다.

session을 true로 적으면 요청마다 세션을 생성해준다.

login API

app.post('/login', passport.authenticate('local', {failureRedirect : '/fail'}), (req, res)=>{
  res.redirect('/')
});

passport.authenticate('local', {failureRedirect : '/fail'}) 는 local 방식으로 아이디와 비번을 인증해달라는 passport라이브러리의 코드를 작성한다.

세션발급과 동봉

passport.serializeUser((user, done)=>{
  done(null, user.id)
});

serializeUserAPI는 세션데이터에 포함된 세션아이디를 발급해서 쿠키에 담아준다.
쿠키는 응답의 헤더에 추가되어 사용자에게 전달되고 사용자의 브라우저는 이 헤더에 담긴 쿠키정보를 브라우저 쿠키 저장소에 저장한다.
이후 다시 요청을 보낼 때 이 쿠키저장소에 있는 쿠키들을 요청에 자동으로 동봉하여 보내게 된다.

로그인 상태 확인

passport.deserializeUser((userID, done)=>{
  db.collection('login').findOne({ id: userID }, function (err, result) {
    done(null, result)
  })
}); 

deserializeUser는 세션아이디가 일치하는 유저의 정보를 DB에서 찾아서 requser프로퍼티를 생성에서 그 값을 넣어준다.

function isAuth(req,res,next){
  if(res.user){
  	next()
  }
  else{
    res.sendStatus(401)
  }
}

deserializeUser가 정상적으로 쿠키를 분석해서 일치하는 유저정보를 찾았다면 req.user는 값이 할당되어있어야 한다.
만약 그렇지 않다면 req.user = undefined가 되어 Falsy값이 되므로 else로 넘어간다.
이를 활용한 isAuth미들웨어를 작성하여 로그인이 필요한 요청에 끼워주면 된다.

app.get('/mypage', isAuth, (req, res) => { 
  console.log(req.user); 
  res.render('mypage.ejs', {}) 
}) 

이 처럼.

👉 검색


<input id = "search-input" type= "text" />
<button id = "search">검색</button>

<script>
  $('#search').click(function(){
    const InputVal = $('#search-input').val();
    window.location.replace('/search?value=' + InputVal)
  });

</script>

검색버튼을 눌렀을 때 input의 value를 검색하는 요청의 주소를 쿼리스트링으로 작성해줬다.

서버에서는 게시물이 100만개가 넘어갈 때 빠르게 조회하기 위해서 binary-search방식을 사용해보자.

DB를 indexing을 해줘야 하는데 mongoDB Atlas로 들어가서 Collection에서 create index를 누르면 된다.

또 search index를 만들면 검색어에서 조사를 제외하고 비교해줄 수 있다.

app.get('/search', (req, res)=>{

  var 조건 = [
    {
      $search: {
        index: '??', // index name
        text: {
          query: req.query.value,
          path: '제목' 
        }
      }
    }
  ] 
  console.log(req.query);
  db.collection('post').aggregate(조건).toArray((err, result)=>{
    console.log(result)
    res.render('search.ejs', {posts : result})
  })
})

aggregate() 함수는 검색조건을 여러개 넣을 수 있게 해준다.

[{조건1}, {조건2}....]와 같은 형태로 넣으면 된다.

0개의 댓글