지난 번 글을 쓰면서 세션 미들웨어의 여러가지 속성에 대해서 자세하게 더 살펴보고 싶다는 생각이 들어서 아예 글을 따로 판다!
처음에는 공식 문서가 눈에 잘 안 들어오긴 했는데... 찾아보면서 억지로 읽다보니 '아하... 이게 이런 속성에 대한 설명이었군?!' 하고 그제서야 눈에 들어오기 시작... 공식 문서 읽는건 정말 어렵다. 공식 문서랑 친해지는 시간이 넘 오래 걸림... 암튼 공식문서를 공부할 겸 번역 해보며 해부해보는 시간 🤩
세션 미들웨어에는 몇 가지 옵션을 줄 수 있다.
세션 데이터는 쿠키키에 자동으로 저장되지 않는다. 단지 sessionID만을 생성해줄 뿐이다. 세션 데이터는 server-side store에 따로 저장을 해주어야 한다.
기본 서버-사이드 세션 스토리지는 MemoryStore
가 제공된다. 하지만 이것은 프로덕션 환경용으로 설계된 것이 아니기 때문에 메모리 누수가 발생하고 단일 프로세스 이상으로 확장되지 않는다. 디버깅 및 개발용으로만 사용하는 것이 좋다고 함.
session
옵션genid
새로 sessionID를 생성하기 위해서 호출하는 함수다. sessionID로 사용될 문자열을 반환하는 함수를 제공할 수 있다. ID를 생성할 때 req
에 첨부된 일부 값을 사용하고 싶다면 req
값이 첫 번째 인수로 제공된다.
따로 설정하지 않을 경우에는 uid-safe
라이브러리리를 사용하여 생성한다.
name
응답으로 보내는 sessionID 쿠키의 이름을 지정할 수 있는 속성이다. 당연히 요청으로 올 때도 읽을 수 있다.
따로 설정해주지 않는다면 connect.sid
라는 디폴트 값으로 생성된다.
Note. 동일한 호스트 이름에서 여러 앱을 실행하는 경우에는 세션 쿠키를 서로분리해야 한다. 앱마다 다른 이름을 설정하는 것이 가장 간단하다.
proxy
보안 쿠키를 설정할 때 역 방향 프록시(reverse proxy)를 신뢰하게 하는 옵션이다.
기본값은 undefined
true
로 설정했을 경우 "X-Forwarded-Proto" 헤더가 사용된다. false
일 경우에는 모든 헤더가 무시되고 직접 TLS/SSL 연결이 있는 경우에만 안전하다고 간주한다. undefined
인 경우 express의 "trust proxy" 설정을 사용한다. resave
요청 중에 세션이 수정되지 않은 경우에도 세션을 세션 저장소에 다시 저장하도록 하는 설정이다. 스토어에 따라서 이것이 필요할 수도 있지만, 경쟁 조건이 발생할 수도 있다. (클라이언트가 서버에 병렬 요청을 하고 한 요청의 세션에 대한 변경 사항이 없더라도 다른 요청이 끝나면 다른 요청이 끝날 때 덮어 쓰일 수 있음)
기본 값은 true
이지만 deprecated 되었다(=더이상 사용되지 않음) 통상적으로 false
를 사용한다
rolling
모든 응답에 세션 식별자 쿠키를 강제로 설정한다. expiration이 원래의 maxAge로 재설정되어 만료 카운트다운이 재설정 된다.
➡️ 세션이 만료되기 전, 새로고침이나 페이지 이동 시 세션 만료를 갱신하는 것임
기본 값은 false
이다.
이 기능을 활성화 할 경우, 세션 식별자 쿠키는 서버에서 세션을 마지막으로 수정한 이후의 maxAge 대신 마지막 응답이 전송된 이후의 maxAge에 만료된다.
이것은 일반적으로 세션 길이가 아닌 짧은 maxAge 값과 함께 사용되어서 진행 중인 서버 상호 작용 중에 발생할 가능성을 줄이면서 세션 데이터의 빠른 시간 초과를 제공한다.
Note. 이 옵션을
true
로 설정했지만saveUninitialized
옵션을false
로 설정하면 초기화되지 않은 세션이 있는 응답에 쿠키가 설정되지 않는다. 이 옵션은 요청에 대해 기존 세션이 로드되었을 때만 동작한다.
saveUninitialized
"초기화되지 않은" 세션을 강제로 저장소에 저장한다. 세션이 새롭지만 수정되지 않은 경우 세션이 초기화되지 않는다. false
를 선택하면 로그인 세션을 구현하거나, 서버 저장소 사용량을 줄이거나, 쿠키를 설정하기 전에 권한이 필요한 법률을 준수하는데 유용하다. false
를 선택하면 클라이언트가 세션 없이 여러 병렬 요청을 하는 경쟁 조건에도 도움이 된다.
기본값은 true
지만 deprecated되었기 때문에...
Note. PassportJS와 함께 세션을 사용하는 경우 Passport는 사용자가 인증된 후 사용할 빈 Passport 개체를 세션에 추가한다. 이는 세션에 대한 수정 사항으로 간주되어 저장된다. 이 문제는 PassportJS 0.3.0에서 수정되었다.
secret
(필수 옵션)Required Option
세션 ID 쿠키에 서명하는데 사용되는 비밀이다. 이 시크릿 값은 Node.js crypto.createHmac에서 지원하는 모든 유형의 값(예: 문자열 또는 버퍼)이 될 수 있다. 이 시크릿 single 혹은 array of multiple secret 배열이 될 수 있다. 시크릿의 배열이 제공되면, 세션 ID 쿠키에 서명하는데 첫 번째 요소만 사용되고 요청시 서명을 확인할 때 모든 요소가 고려된다. 시크릿 자체는 사람이 쉽게 구문 분석을 하지 않아야 하고, 임의의 문자 집합이 가장 좋다.
예시
시크릿 값을 변경하면 기존의 세션이 모두 비활성화 된다. 세션을 비활성화하지 않고 시크릿을 rotate 하려면 배열의 첫 번째 요소로 새 시크릿을 제공하고, 이후 요소로 이전 시크릿을 포함해야 한다.
Note. HMAC-256은 세션 ID에 서명하는 데 사용된다. 때문에 시크릿 값은 적어도 32바이트의 엔트로피를 포함해야 한다.
store
세션 저장소는 MemoryStore
인스턴스로 기본 설정된다.
unset
req.session
설정 해제 결과를 제어한다. (삭제나 null로 설정 등을 통해서)
기본값은 keep
이다.
destroy
: 응답이 종료되면 세션이 파괴(삭제)된다.keep
: 스토어의 세션은 유지되지만 요청 중에 수정한 내용은 무시되고 저장되지 않는다. cookie
옵션세션 ID 쿠키의 설정 객체이다. 기본 값은 { path: '/', httpOnly: true, secure: false, maxAge: null }
이고 다음은 이 객체에서 설정할 수 있는 옵션들이다.
cookie.domain
도메인 Set-Cookie의 특성 값을 지정한다. 기본적으로 도메인은 설정되지 않고, 대부분의 클라이언트는 쿠키가 현재 도메인에만 적용되는 것으로 간주한다.
cookie.expires
특정 날짜 객체를 Expires Set-Cookie 값을 지정한다. 기본적으로 만료는 설정되지 않는다. 대부분의 클라이언트는 이를 "비영구 쿠키"로 간주하고 웹 브라우저 응용 프로그램을 종료하는 것과 같은 조건으로 삭제한다.
Note. 옵션에서 expires와 maxAge가 모두 설정되 어 있으면 개체에 정의된 마지막 항목이 사용된다.
Note. expires 옵션은 직접 설정해서는 안 되고 maxAge 옵션만 사용한다.
cookie.httpOnly
HttpOnly Set-Cookie의 특정 불린 값을 저장한다. true
라면 HttpOnly가 설정되고, 그렇지 않으면 설정되지 않는다. 기본적으로 HttpOnly 특성이 설정된다.
Note. 호환되는 클라이언트는 클라이언트 측 자바스크립트가 document.cookie에서 쿠키를 볼 수 없도록 설정하기 때문에 이를
true
로 설정할 때 주의해야 한다.
cookie.maxAge
Expires Set-Cookie의 특성을 계산할 때 사용할 수(밀리초 단위)를 지정한다. 이 작업은 현재 서버 시간을 사용하고 값에 maxAge millisecond를 추가하여 Expires datetime을 계산한다. 기본적으로 최대 사용 기간은 설정되지 않는다.
Note. 옵션에서 expires와 maxAge가 모두 설정되어 있으면 개체에 정의된 마지막 항목이 사용된다.
cookie.partitioned
Partitioned Set-Cookie 특성에 대한 불린값을 지정한다. true
에서는 Partitioned 특성이 설정되고, 그렇지 않으면 설정되지 않는다. 기본적으로 partitioned 특성은 설정되지 않는다.
Note. 이것은 아직 완전히 표준화되지 않은 속성이며, 앞으로 변경될 수 있다. 이것은 또한 많은 클라이언트가 이 속성을 이해할 때까지 무시할 수 있음을 의미한다.
cookie.path
Path Set-Cookie 값을 지정한다. 기본적으로 도메인의 루트 경로인 '/'로 설정된다.
cookie.priority
문자열을 Priority Set-Cookie 특성의 값으로 지정한다.
low
는 Priority 특성을 Low로 설정한다.
medium
은 Priority 속성을 설정하지 않을 경우 기본 우선 순위인 'Medium'으로 설정한다.
high
은 Priority 특성을 '높음'으로 설정한다.
Note. 이것은 아직 완전히 표준화되지 않은 속성이며, 앞으로 변경될 수 있다. 이것은 또한 많은 클라이언트가 이 속성을 이해할 때까지 무시할 수 있음을 의미한다.
cookie.sameSite
SameSite Set-Cookie 특성의 값이 되도록 부울 또는 문자열을 지정한다. 기본적으로 이 값은 false
이다.
true
는 엄격한 동일 사이트 적용을 위해 SameSite 특성을 Strict로 설정한다.
false
는 SameSite 특성을 설정하지 않는다.
lax
는 동일 사이트를 느슨하게 적용하기 위해 SameSite 속성을 Lax로 설정한다.
none
은 명시적인 크로스 사이트 쿠키에 대해 SameSite 특성을 없음으로 설정한다.
strict
는 엄격한 동일 사이트 적용을 위해 SameSite 특성을 Strict로 설정한다.
Note. 이것은 아직 완전히 표준화되지 않은 속성이며, 앞으로 변경될 수 있다. 이것은 또한 많은 클라이언트가 이 속성을 이해할 때까지 무시할 수 있음을 의미한다.
Note. SameSite 속성이
none
으로 설정된 경우 보안 속성을 true로 설정해야 하는 사양 초안이 있다. 일부 웹 브라우저 또는 다른 클라이언트에서 이 사양을 채택하고 있을 수 있다.
cookie.secure
Secure Set-Cookie 특성에 대한 불린 값을 지정한다. true
로 지정할 시 Secure 특성이 설정되고 그렇지 않으면 설정되지 않는다. 기본적으로 Secure 특성은 설정되지 않는다.
Note. 브라우저에 HTTPS 연결이 없는 경우 준수 클라이언트는 나중에 쿠키를 서버로 다시 보내지 않으므로 이를
true
로 설정할 때 주의해야 한다.
secure: true
는 권장 옵션이다. 하지만 https 지원 웹사이트가 필요하다. 즉, 보안 쿠키의 경우 HTTPS가 필요한 것이다. 보안이 설정되어 있고 HTTP를 통해 사이트에 액세스하면 쿠키가 설정되지 않는다. 프록시 뒤에 node.js가 있고 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 }
}))
프로덕션에서 보안 쿠키를 사용하지만 개발 중인 테스트를 허용하는 경우, NODE_ENV in express를 기반으로 이 설정을 실행하는 예시:
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
로 설정하여 이 설정이 결정된 연결 보안과 자동으로 일치하도록 할 수도 있다. 이 설정을 사용할 때 주의해야 한다. 일단 쿠키가 HTTPS로 설정되면 더 이상 HTTP를 통해 표시되지 않으므로 사이트가 HTTP와 HTTPS 둘 다로 사용 가능한 경우에는 이 설정을 사용할 때 주의해야 한다. 이는 Express "trust proxy" 설정이 개발 대 운영 구성을 단순화하도록 적절하게 설정되어 있을 때 유용하다.
임시 글에서 100만년은 잠들어있을 것 같아 정리하지 못한 나머지 설정도 살펴보고 뒤늦게나마 올린다,,, 세션 사용해서 로그인 구현한 거는 시리즈 꼭 마무리해야지 ㅎㅎ... 얼마나 걸릴지는 모르겠당 ^_^ 오랜만에 노드~
sameSite와 secure 덕분에 한참 고생하고, maxAge 관련해서도 고생한 기억이 난다. 쿠키 너 정말~ 힘든 녀석이었어~
내가 한 번씩 싹 번역한 세션 객체 옵션 외에도 사용할 수 있는 함수들, 세션 스토어 종류들도 많이 나와있다. 필요할 때 한 번 쓱 훑어보는 것이 좋을듯...