인디노트

[Node.js] express-session 본문

개발 플랫폼 및 언어/노드 Node & NPM

[Node.js] express-session

인디개발자 2018. 11. 2. 18:53

# Installation
$ npm install express-session

#API
var session = require(‘express-session’)

# session(option)
주어진 옵션들과 함께 세션 미들웨어를 만드세요.

Note 세션데이터는 쿠키 안에 저장되지 않아요. 세션ID만 저장해요. 세션데이터는 서버사이드에 저장됩니다.

Warning 서버쪽의 기본 세션 공간인 MemoryStore는 제품 환경을 위해 만들어 지지 않았어요. 대부분의 조건에서 메모리가 부족할겁니다. 싱글프로세스를 커버하지 못해요. 이말은 즉, 디버깅이나 개발용이다 이겁니다.

저장공간 리스트를 보려면 여기 누르세요 compatible session stores.

express-session

www.npmjs.com

# Options
express-session은 options object안에 이 요소들을 넣었습니다.

cookie 
session ID cookie 를 설정하세요. 다른 값들에서의 더 많은 정보를 위해 아래 Cookie options 섹션을 보세요.
기본 설정값은 이와 같습니다.
 { path: ‘/’, httpOnly: true, secure: false, maxAge: null }

genid
새 세션 ID를 만들기 위해 요청하기 위해 사용합니다. 세션 id로 사용될 string 을 리턴합니다. ID를 생성할때 몇몇 값들을 req에 포함시키고 싶다면 첫번째 인자로 req를 주면 됩니다.

기본값은 ID를 생성하기 위해 uid-fase 라이브러리를 사용하는 함수입니다.

NOTE ID만들 때 조심하세요. 그래야 당신의 세션에 문제가 안생겨요.

app.use(session({
 genid: function(req) {
 return genuuid() // use UUIDs for session IDs 
 },
 secret: ‘keyboard cat’
}))

name
response안에 설정하기 위한 세션 ID 쿠키 이름입니다.

NOTE 한 호스트(hostname+port)에 여러앱을 가지고 있다면, 각각으로부터 세션 쿠키를 분리할 필요가 있습니다. 가장 간단한 방법은 각각의 앱마다 다른 이름은 지정하는 것입니다.

proxy
secure cookies 를 셋팅할 때는 reverse proxy 를 신뢰하세요.(?)

기본값은 undefined 입니다.
true — “X-Forwarded-Proto” header 가 사용될 것입니다.
false — 모든 헤더들은 무시되어 질것이고, 커넥션들은 direct TLS/SSL 커넥션이 있어야만 보안을 고려하게 될것입니다.
undefined — express에 있는 “trust proxy” 셋팅을 사용하게 됩니다.

resave
요청하는 동안 수정이 없다 하더라도 세션은 세션저장공간에 강제적으로 다시 저장 될것입니다. 저장공간에 따라 이것이 필수가 될 수가 있는데, 이는 또는 client가 두 병렬 request를 서버에 보낼 때 문제(race condition)를 일으키기도 합니다. 한쪽 request가 종료 되었을 때, 한 request가 오버라이트 되면서 세션이 수정되면서.. (이는 당신이 어떤 저장공간을 쓰냐에 따라 달라집니다)

기본 값은 true인데 이는 바뀔 것입니다. 당신의 경우에는 무엇이 가장 적절한지 선택하세요. 보통은 false를 사용할 겁니다.

저장 스토어에 이게 필요한지는 어떻게 알 수 있을까요? 가장 쉬운 방법은 스토어에 touch 메쏘드가 구현되어 있는지 확인하는 것이다. 그러면 간단히 resave를 false로 셋팅할 수 있다. 만약 메쏘드가 구현되어 있지 않고 스토어가 세션에 데이터 만료 date를 셍팅해놨다면, 당신은 resave: true로 셋팅하면 된다.

rolling 
강제적으로 세션 식별자 쿠키는 모든 response에 셋팅될 것입니다. maxAge의 만료date는 리셋될 것 입니다.

기본값은 false입니다.

NOTE 이 옵션이 true지만 saveUnitialized option이 false 라면, 쿠키는 초기화되지 않은 세션과 함께 response 에 셋팅되지 않을거에요.

saveUninitialized
초기화되지 않은채 스토어에 저장되는 세션을 말한다. 새로 만들어져, 수정되지 않았을 때, 세션은 초기화되지 않는다. false를 선택하는 것은 로그인 세션을 만들 때,서버 사용량을 줄일 때, 또는 쿠키를 셋팅하기전에 퍼미션을 요구하는 규정을 적용할 때, 유용하다. false를 선택하는 것은 client가 세션 없이 여러 병렬 request를 만들었을 때 발생하는 race condition에 유용하다.

기본값은 true이다. 그러나 점점 바뀔 것이다. 당신이 연구해서 당신의 환경에서 뭐가 더 적절한지 선택해라.

NOTE 만약 PASSPORT.JS과 경합하는 과정에서 세션을 사용하는 것이라면, PASSPORT는 유저를 인증하고 난뒤에 사용하기 위해 빈 PASSPORT객체를 생성할 것이다. 빈 객체는 세션을 위해 변경되는 것으로 처리될 것이다. 그래서 그것이 저장될 것이다.

secret
Required option

세션ID쿠키를 서명하는데 사용될 비밀이다. String 하나가 될 수도 있고, array 형식이 될 수도 있다. 
만약 array 형식으로 제공된다면, 첫번째 요소만 세션 ID 쿠키를 서명하는데 쓰이고, 모든 요소는 request 안에 서명을 확인 할 때 쓰여질 것이다.

store
새로운 메모리 스토어 인스턴스를 위한 기본 세션스토어 인스턴스이다.

unset
셋팅되지 않은 req.session ( delete 를 한다거나, null로 셋팅하는 등의..?) 의 결과를 컨트롤한다.

기본값은 keep이다.
‘destroy’ response가 끝나면 세션은 파기될 것이다. (삭제)
‘keep’ 스토어 안에 세션은 유지될 것이다. 그러나 request 중에 만들어지는 수정사항들은 무시되거나 저장되지 않는다.

Cookie options
NOTE 1.5.0 버전부터 cookie-parser middleware는 더 이상 이 모듈이 돌아가는데 필요하지 않아졌다. 지금 이 모듈은 직접 req/res에 cookie를 읽고 쓰기를 한다. 이 모듈과 cookie-parser 사이에서 secret이 같지 않다면 cookie-parser를 사용하는 것의 결과는 이슈가 된다.

확인해야 될 사항 : true 옵션을 사용하기를 추천한다. 그러나 그것은 https 가 사용가능한 웹사이트여야 한다. 그러니까.. 쿠키를 보호하기 위해 HTTPS가 필수라는 것이다. 만약 secure가 설정되면, 당신이 http로 사이트를 접근할 때, 쿠키는 설정되지 않는다. 만약 당신이 proxy뒤에 nodejs를 돌리고 있고, secure: true 라면 express 안에 “trust proxy”를 설정해야 한다.

var app = express()
app.set(‘trust proxy’, 1) // trust first proxy 
app.use(session({
 secret: ‘keyboard cat’,
 resave: false,
 saveUninitialized: true,
 cookie: { secure: true }
}))

제품안에서 secure cookie들을 사용하기 위해서, 개발중에 테스트를 위해 허가가 있어야 하는데, 다음은 express에서 NODE_ENV를 기초로한 설정을 사용할 수 있게 하는 예제이다.

var app = express()
var sess = {
 secret: ‘keyboard cat’,
 cookie: {}
}
 
if (app.get(‘env’) === ‘production’) {
 app.set(‘trust proxy’, 1) // trust first proxy 
 sess.cookie.secure = true // serve secure cookies 
}
 
app.use(session(sess))

cookie.secure 옵션은 커넥션의 보안을 결정하는데 있어서 자동적으로 맞춰지도록 셋팅하기위해 특별히 auto로 설정될 수 있다. 이 셋팅을 이용할 때 만약 http나 https 둘다 사용할 때는 조심해야 한다. 쿠키가 https로 설정되면 더이상 http에서는 볼 수가 없게된다. express “trust proxy”셋팅을 단순히 개발과 제품 설정으로 적절하게 설정하면 아주 유용할 것이다.

자연스레 cookie.maxAge 를 null로 한다는 것은, 파기되지 않는 파라미터를 설정하여 쿠키가 브라우저 세션 쿠키로 되도록 한다. 사용자가 브라우저를 닫을 때 쿠키(세션)은 삭제될 것이다.

req.session
세션데이터를 저장하거나 접근하기 위해, 간단히 req.session 을 사용하면 되는데 이는 보통 JSON으로 스토어에 serialized 되어 있다( 직렬화 ) 그래서 순서를 지니며 서로 연결된 오브젝트들이 기본적으로 좋다(?). 예를 들어, 아래는 유저 특정 뷰 카운터를 보여준다.

// Use the session middleware 
app.use(session({ secret: ‘keyboard cat’, cookie: { maxAge: 60000 }}))
 
// Access the session as req.session 
app.get(‘/’, function(req, res, next) {
 var sess = req.session
 if (sess.views) {
 sess.views++
 res.setHeader(‘Content-Type’, ‘text/html’)
 res.write(‘<p>views: ‘ + sess.views + ‘</p>’)
 res.write(‘<p>expires in: ‘ + (sess.cookie.maxAge / 1000) + ‘s</p>’)
 res.end()
 } else {
 sess.views = 1
 res.end(‘welcome to the session demo. refresh!’)
 }
})

session.regenerate()
세션을 재생성하기 위해서 단순히 이 함수를 사용하면 된다. 완료되자마자, 새로운 세션 ID와 세션 인스턴스가 req.session에 초기화 될것이다.
req.session.regenerate(function(err) {
 // will have a new session here 
})

session.destroy()
세션을 파괴하면 req.session이 삭제될 것이다. 그리고 다음 요청 때 제 생성될것이다.
req.session.destroy(function(err) {
 // cannot access session here 
})

session.reload()
세션데이터를 다시 불러온다.
req.session.reload(function(err) {
 // session updated 
})

session.save()
세션을 스토어에 다시 저장한다. 스토어에 있는 컨텐츠를 메모리안에 있는 컨텐츠로 대체한다.
( 스토어가 뭔가를 하기는 하는데.. 정확한 구현에 대해서는 스토어의 문서를 참조해라)

만약 session 데이터가 바뀐게 있으면 이 메쏘드는 자동으로 http response 끝에서 요청된다.( 이 과정에서 여러가지 옵션들이 바뀔 수 있다. ) 
그래서 보통 이 메쏘드는 따로 요청할 필요가 없다.

롱라이브 request나 웹소켓에서는 이 메쏘드가 유용할 수도 있다.
req.session.save(function(err) {
 // session saved 
})

session.touch()
각각의 세션은 그것과 관련된 유니크 ID를 가지고 있다. 이 요소는 세션ID를 가지고 있고 이것은 바꿀수는 없다.

req.session.cookie
 각각의 세션은 유니크 쿠키 오브젝트를 동반하고 있다. 이것은 당신이 매 접속마다 세션 쿠키를 대체할 수 있도록 허락한다. 예를 들어 우리는 쿠키가 user-agent 지속기간동안만 남겨지도록 req.session.cookie.expires 를 false로 설정할 수 있다.

cookie.maxAge
 req.session.cookie.maxAge는 남아있는 시간을 밀리초로 리턴한다. 또한 .expires 프로퍼티레 적용하기위해서 적절하게 새로운 값을 재할당한다.

var hour = 3600000
req.session.cookie.expires = new Date(Date.now() + hour)
req.session.cookie.maxAge = hour

예를 들어 maxAge가 60000(1분)으로 설정될 때, 30초는 흐르고나서 현재 요청이 종료될 때까지는 3000을 리턴한다. 이는 req.session.touch()가 req.session.maxAge를 원래 시간으로 리셋할때 불려진다.
req.session.cookie.maxAge // => 30000

req.sessionID
올라온 세션의 id를 얻기 위해 req.sessionID에 접근해라. 이는 세션이 만들어지고 올라올 때, 단순히 읽기전용 값으로 설정된 것이다.

Session Strore Implementation

모든 세션 스토어는 반드시 EventEmitter가 되어야 하고 구체적으로 메쏘드를 구현해야 한다. 다음 메쏘드들은 required, recommended, optional 리스트이다.
Required 메쏘드는 스토어에서 이 모듈이 항상 요청 될 것이다.
Recommended 메쏘드는 스토어에서 이 모듈이 사용가능할 때만 요청될 것이다.
Optional 메쏘드는 항상 요청되지는 않지만 유저를 위해 현재 유니폼 스토어를 도와준다.

For an example implementation view the connect-redis repo.

store.all(callback)
optional

이 옵셔널 메쏘드는 스토어에서 모든 세션을 arrary로 얻을 때 사용된다. callback은 callback(error,sessions)을 호출할 것이다.

store.destroy(sid,callback)
Required

이 required 메쏘드는 스토어에서 sessionID에 매칭되는 세션을 삭제할 때 사용된다. callback은 세션이 사라지자마자 callback(error)을 호출한다.

store.clear(callback)
optional
이 optional 메쏘드는 스토어의 모든 세션을 삭제할 때 사용된다. callback은 스토어가 깨끗하게 비어지자마자 callback(error)을 호출한다.

store.length(callback)
optional
이 optional 메소드는 스토어의 모든 세션의 갯수를 얻을 때 사용된다. callback은 callback(error,len)을 호출한다.

store.get(sid,callback)
Required
이 required 메쏘드는 스토어에서 sessionID(sid)와 배칭되는 세션을 얻을 때 사용된다. callback은 callback(error,session)을 호출한다.
만약 세션을 찾게 되면 세션 인자는 유효한 세션이 들어있을 것이다. 만약 유효하지 않은 세션이면 null이나 undefined 이 들어갈 것이다.(에러는 아님)
 callback(null,null)처럼 error.code ===’ENOENT’ 가 동작할 때, 특수한 경우가 발생한다.

store.set(sid,session,callback)
Required

이 required 메쏘드는 스토어에 주어진 sessionID(sid)와 세션을 집어 넣을 때 사용된다. callback은 세션이 스토어에 셋업되면 callback(error)을 호출한다.

store.touch(sid,session,callback)
Recommended

이 recommended 메쏘드는 주어진 세션으로 “touch” 하는데 사용된다. callback은 세션이 touch하자마자 callback(error)을 호출한다.
이는 스토어가 유휴한 세션을 자동으로 삭제할 때 사용한다. 이 메쏘드는 스토어에 주어진 세션이 액티브 상태라고 신호를 줄 때 사용된다. 아마 타이머도 재셋팅 할 듯.

반응형
Comments