티스토리 뷰

시리즈/Web

쿠키, 세션, passport.js

빅또리 2021. 4. 30. 17:05

 

쿠키

An HTTP cookie(also called web cookie, Internet cookie, browser cookie, or simply cookie) is a small piece of data stored on the user's computer by the web browser while browsing a website. Cookies were designed to be a reliable mechanism for websites to remember stateful information

 

 

 

 

유저단은 브라우저가 알아서 해주니까 신경안써도 되고,

node.js express 서버에서는 예를들어 이런식의 작업들을 하면 쿠키라는 것을 적용할 수 있다.

 

(1) set-cookie

(2) http request 올때마다 요청헤더에 들은 쿠키 보고 유저 정보 판단하기

 

 

 

 

 

 

 

 

 

 

 

 

세션

 

 

 

 

 

 

express-session 모듈

express-session이 작동하는 방식

 

 

🌎 이 모듈을 사용하는 개발자가 작성해야 하는 부분.

 

(1) session 미들웨어 등록

- secret : use it to encrypt the sessionId

세션아이디 해싱하는데 사용하는 키 값인 것 같다. (보안을 위해 쿠키에 적힐 세션아이디 암호화. 네트워크를 통해 오고가고 할 값이니까)

- resave : 파랑(2) 에서 session 값에 변화 없었어도 저장소에 save하는 과정 꼭 할건지.

- saveUnitialized : Forces a session that is "uninitialized" to be saved to the store. A session is uninitialized when it is new but not modified.

(기존에 sid가 없던 새 요청인데 서버 처리에서 세션관련 처리도 없는 경우에도 save 할거냐? 이런거 같은데 잘 모르겠음.)

- store : 어떤 session 저장소를 사용할지도 다양한 선택지가 있는데, (mongodb, mysql, lowdb, sqlite, file, ... 등등등)

미들웨어 등록하는 코드에서 옵션으로 주면 된다.

 

(2) 해당 request에 대한 서버 처리 코드 (req.session으로 세션정보 접근)

 

여기서 해당 session 삭제하고 싶으면 req.session.destroy 메소드 호출하면 된다.

 

 

 

 

🌺 session미들웨어가 대신 해주는 일

 

(1) request 쿠키에 들어있는 세션 아이디 확인해서,

세션저장소의 해당 세션정보 req.session으로 참조할 수 있게 만들기.

 

만약 세션 아이디 없으면 새로운 요청이니까 이 미들웨어가 우리 대신 고유한 세션 아이디 만들고, request 헤더에 set-cookie 하는 그런 과정도 대신 해줄 것.

 

(2) 보라(2) 작업 이후 변경된 session 내용 다시 세션 저장소에 저장하기.

Save the session back to the store, replacing the contents on the store with the contents in memory
This method is automatically called at the end of the HTTP response if the session data has been altered. Because of this, typically this method does not need to be called.
There are some cases where it is useful to call this method, for example, redirects, long-lived requests or in WebSockets

특정 경우 (리다이렉트, long-lived request, websocket) 명시적으로 이 메소드를 호출하고 싶으면 (비동기 문제 해결 등의 이유로) req.session.save 메소드를 사용하면 된단다.

기본적으로는 session 정보가 modified 됐으면 이 작업 알아서 해줌.

 

 

 

 

 

 

 

 

 

 

passport.js

Passport is authentication middleware for Node.
It is designed to serve a singular purpose: authenticate requests

passport 모듈이 내부적으로 사용하는 다른 모듈

 

 

 

passport.js를 쓰기 위해 코드상 필요한 3부분 

 

1. 각종 필요한 모듈 require, 미들웨어 사용 설정

serializeUser랑 deserializeUser호출이 계속 안돼서 좀 헤맸는데 바디파서 포함 안시킨거랑 미들웨어 순서 틀린 문제 때문이었다.

 

 

+익스프레스 4.16.0 버전부터 body-parser 일부 기능이 익스프레스에 내장되어 따로 설치할 필요 없다고 한다.

app.use(express.json())

app.use(express.urlencoded({extended:false})

-> 이 두가지는 내장 json, url 쿼리스트링 파싱해서 req.body 객체에 넣어주는 역할

 

(단, raw나 text 형식의 해석이 필요할때는 따로 body-parser 모듈을 설치해야 한다고 함.)

 

 

2. strategy, session관련 configuration.

간단히 하려고 db에서 사용자 찾는부분 빼고 그냥 owner변수랑 비교하게만 만들었다.

 

 

3. 라우팅 관련 코드. 어떤 http 요청에 대해 passport.authenticate() 함수 호출해서 요청에 대한 인증 처리를 할건지.

 

전체 코드

const express = require('express');
const app = express();
const http = require('http');
const server = http.createServer(app);
//db (세션저장소로 사용할)
const lowdb = require('lowdb');
const FileSync = require('lowdb/adapters/FileSync');
const adapter = new FileSync('./db/session.json', { defaultValue: { sessions: [] }});
const db = lowdb(adapter);
//session
const session = require('express-session')
const LowdbStore = require('lowdb-session-store')(session);
//passport
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;


app.use(express.urlencoded({ extended: false }));
app.use(session({
  secret: 'keyboard cat',
  resave: false,
  saveUninitialized: true,
  store: new LowdbStore(db.get('sessions'), {
    ttl: 86400
  }),
  cookie:{secure:false}
}))
app.use(passport.initialize());
app.use(passport.session());



const owner = {name:"ddory", pwd:"12345"};

passport.serializeUser(function(user, done) {
  console.log("serializeuser");
  done(null, user.name);           
});
passport.deserializeUser(function(id, done) {
  console.log("deserializeuser");
  done(null, "this will be req.user value");      //req.user에 주입해주는 것
});

passport.use(new LocalStrategy(
  function(username, password, done) {
    console.log("verify callback",username,password);
    if(!owner){ return done(err); }
    if(username==owner.name && password==owner.pwd){
      done(null, owner);
    }else{
      done(null,false,{message:"failed to login"});
    }
  }
));

//server logic
app.get('/', (req, res) => {
  console.log("req.user",req.user);
  res.send(`welcome ${req.user} ~!`);
});

app.get('/login', (req, res) => {
  res.sendFile(__dirname + '/passport.html');
});

//custom callback 부분에서 했던 것들 미들웨어가 알아서 해주는 간단버전
app.post('/login_process',
  passport.authenticate('local', { successRedirect: '/',
                                   failureRedirect: '/login'})
);

server.listen(3000, () => {
  console.log('listening on 3000 port');
});

 

 

 

워크플로우

어우 정신사나워

 

 

+req.isAuthenticated() 

인증된 유저인지 아닌지에 대한 bool 값 (req.user가 있는 케이스면 true, 나머지는 false 일듯)

어떤 요청에서도 이 메소드 호출 가능함.

 

(아직 세션에 인증정보 없는 요청에도 (아마) passport.initialize 미들웨어가 이 함수 주입해서 req.isAuthenticated는 함수가 아닙니다 이런 에러 안뜨고 false로 잘 작동)

 

 

+req.logout()

Invoking logout() will (1)remove the req.user property and (2)clear the login session (if any)

(1) req.logout

passport 미들웨어가 주입한 메소드

- req.user 프로퍼티 삭제되고

- 세션에서 passport.user 부분만 삭제

 

(2) req.session.destroy

express-session의 미들웨어가 주입한 메소드

- 아예 해당 세션 삭제

 

    

 

 

 

참고하면 좋은 글 : http://toon.io/understanding-passportjs-authentication-flow/

😎 다음편 : 2021.04.30 - [분류 전체보기] - passport.js의 OAuth2.0

'시리즈 > Web' 카테고리의 다른 글

authorization 방법들 비교 (쿠키, 세션, JWT)  (0) 2021.05.07
passport.js의 OAuth2.0  (0) 2021.04.30
proxy와 CORS 2편  (0) 2021.04.22
proxy와 CORS 1편  (1) 2021.04.22
Real Time Web 선택지 비교  (0) 2021.02.16
댓글
공지사항
최근에 올라온 글