Session
Session
1.세션 작동 방식 -> 세션 데이터 자체는 서버에 저장 -> 클라이언트(브라우저)에는 세션 ID가 쿠키(connect.sid)로 저장
2.세션 저장소가 아닌 왜 쿠키에 저장이 되는가? -> 브라우저에서 쿠키를 확인하면 세션 ID가 보인다 -> 세션 데이터 자체는 서버에 저장되고 세션 ID만 클라이언트 측의 쿠키에 저장(클라이언트가 세션 데이터에 직접 접근하거나 조작할 수 없게 되어 보안이 강화) -> 서버는 세션 ID를 통해 해당 세션 데이터를 찾아서 사용할 수 있습니다
3. 세션 저장소 -> 기본적으로는 nest.js는 메모리에 세션을 저장하기 떄문에 서버를 재시작하면 모든 세션 데이터가 사라진다.
4. 장점 -> 쿠키는 HTTP 요청에 자동으로 포함되어 전송됩니다. 클라이언트가 서버에 요청을 보낼 때마다 세션 ID를 명시적으로 포함시키지 않아도 되므로, 세션 ID를 쿠키에 저장하는 것이 더 편리합니다.
Session 을 직접 실행하기 전에...
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import * as session from "express-session";
import { ValidationPipe } from '@nestjs/common';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.useGlobalPipes(new ValidationPipe({ transform: true}));
app.use(
session({
secret: "당신이 원하는 문자열", ex)"ABCD"// 세션 ID 쿠키에 서명하는 데 사용되는 비밀 키입니다
resave: false, //세션이 수정되지 않았더라도 강제로 다시 저장할지 여부를 설정합니다. false로 설정하면 세션이 변경되지 않았을 때 저장을 건너뛰어 성능을 향상시킵니다
saveUninitialized: false, //초기화되지 않은 세션을 저장소에 저장할지 여부를 설정합니다. false로 설정하면 세션이 필요하기 전까지는 쿠키를 클라이언트에 전송하지 않습니다.
cookie: {
secure: false, // HTTPS를 통해서만 쿠키를 전송할지 여부를 설정합니다. 현재 false로 설정되어 있어 HTTP에서도 쿠키를 전송합니다. 프로덕션 환경에서는 true로 설정하는 것이 좋습니다.
// maxAge: 1000 * 60 * 60 * 24, // 쿠키 유효 기간 1일 (밀리초 단위)
maxAge: 60000, // 쿠키의 유효 기간을 밀리초 단위로 설정합니다
sameSite: 'strict' // 크로스 사이트 요청에 대한 쿠키 전송 정책을 설정합니다. 'strict'는 같은 사이트의 요청에만 쿠키를 전송합니다. 가장 엄격한 설정입니다
}
}),
);
app.enableCors({
origin: true,
methods: 'GET,HEAD,PUT,PATCH,POST,DELETE',
allowedHeaders: 'Content-Type, Accept , Authorization , X-XSRF-TOKEN',
credentials: true,
});
await app.listen(4000);
}
bootstrap();
을 설정해준다
controller에서 session을 사용할려면 @nestjs/common에서 Session을 사용해야한다
ex)import { Session } from '@nestjs/common';
Session 작동 방식
일반적인 Cookie로 클라이언트에 설정했을 시
#nest.js
@Post('cookielogin')
async cookielogin(@Req() req: Request, @Res() res: Response, @Body() createauth : CreateAuthDto) {
console.log(createauth)
res.cookie('connect.sid', createauth.ID, { path: '/' }); // createauth.ID를 클라이언트 connect.sid(다르게 해도 됨)라는 이름으로 설정
res.send('Login successful');
}
에 먼저 쿠키로 값을 설정해보겠습니다(세션이 아닌 쿠키) CreateAuthDto는 username(Id)와 password를 입력받는다.
현재 username : HELLO 를 입력하였다.
결과 : 1-2(사진)과 같이 일반적으로 쿠키로 설정하면 그냥 암호화가 안되고 Hello가 출력되는 걸 볼수있다(보안적으로 안좋다).
Session 을 이용해 Session ID를 설정했을 시 (1-1 상황에서)
#nest.js
@Post('sessionlogin')
async sessionlogin(@Body() loginData: { username: string; password: string },@Session() session: Record<string, any>) {
// 여기서 실제로는 데이터베이스에서 사용자 확인 등의 로직이 들어가야 합니다.
if (loginData.username && loginData.password ) {
session.userId = 1; // 사용자 ID를 세션에 저장
session.username = loginData.username; // 사용자 이름을 세션에 저장
// 비밀번호 대신 로그인 상태를 나타내는 플래그를 저장
session.isLoggedIn = true;
return { message: 'Logged in successfully' };
} else {
return { message: 'Invalid credentials' };
}
}
에 먼저 세션으로 값을 설정해보겠습니다(쿠키가 아닌 세션) username에 똑같이 HELLO를 입력했는데
1-3(사진)과 같이 암호화 되어 connect.sid라는 이름으로 쿠키에 저장된 세션 ID를 확인할수 있다.
(쿠키는 이름을 설정한 반면에 세션은 이름을 설정안해도 connect.sid라는 이름으로 자동 설정된다)
결과적으로 Cookie를 사용했을때보다 세션 ID를 사용하면 보안측면에서도 좋다.
세션 저장소가 아닌 왜 쿠키에 저장이 되는가?
데이터는 서버에 저장되는걸 확인하는 코드이다.
1-1(사진)과 같이 로그인을 안했을떄는 cookie값에 아무것도 없으니 1-4(사진)과 같이 세션 정보만 출력된다.
하지만 1-3(사진)과 같이 로그인을 했을떄는 cookie값에 세션 ID가 있으니 1-5(사진)과 같이 사용자에 대한 정보를 같이 출력한다. (1번에 대한 설명을 보면 #3 개를 설정하여서 3개가 나오는걸 볼수 있다.
session.userId = 1; // 사용자 ID를 세션에 저장
session.username = loginData.username; // 사용자 이름을 세션에 저장
session.isLoggedIn = true; // 비밀번호 대신 로그인 상태를 나타내는 플래그를 저장)
결과적으로 암호화(?)된 세션 ID만 cookie에 저장되고 데이터는 서버에 저장된다(자동 로그인에 사용할수있다)
#nest.js
@Get('check-session')
checkSession(@Session() session: Record<string, any>) {
console.log('Session data:', session);
return { isLoggedIn: session.isLoggedIn || false };
}
장점
쿠키 값을 설정하면 클라이언트에서 인증을 할때마다 코드를 추가하여서 데이터를 같이 보내야하는거 아니에요? 라는 생각이 들수있다.
#React.js
const check = async(event) => {
event.preventDefault();
const response = await fetch("http://localhost:4000/auth/check-session", { method: "GET", headers: { "Content-Type": "application/json" }, credentials: 'include' });
if (!response.ok) {
throw new Error("Fetch is not");
}
const resData = await response.json();
console.log(resData)
}
#credentials: 'include'의 의미
credentials: 'include'를 설정하면,
요청을 보낼 때 항상 쿠키, HTTP 인증 정보(예: 기본 인증, 다이제스트 인증), 및 TLS 클라이언트 인증 정보를 포함시킵니다.
이를 통해 클라이언트와 서버 간의 인증된 상태를 유지할 수 있습니다.
예를 들어, 사용자가 로그인한 상태에서 서버에 요청을 보낼 때 이 옵션을 사용하면 세션 쿠키를 포함하여 요청할 수 있습니다.
위 코드와 같이 요청을 보낼떄 credentials: 'include'적어주면 쿠키값도 요청을 해 check-session(2번 설명 api)을 사용할수있다 만약에 credentials: 'include'를 요청을 할떄 적어 주지않으면 1-4(사진)과 같이 세션 정보만 출력한다
#그 외 설명
1번 설명에 있는 api(sessionlogin)를 호출할때도 credentials: 'include'를 설정해주어야지 클라이언트에 세션 ID가 설정된다.
credentials: 'include'설정을 안해주면 1-3(사진)과 같이 cookie값이 설정이 안된다 1-1(사진)과 같이 빈 쿠키 화면을 볼수있다.
#React.js(sessionlogin api호출)
const sessionLogin = async(event) => {
event.preventDefault();
const response = await fetch("http://localhost:4000/auth/sessionlogin", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ username: username, password: password }), credentials: 'include' });
if (!response.ok) {
throw new Error("Fetch is not");
}
const resData = await response.json();
console.log(resData)
}
#logout에 대한 코드
#React.js
const sessionlogout = async(event) =>{
event.preventDefault();
const response = await fetch("http://localhost:4000/auth/check-session", { method: "GET", headers: { "Content-Type": "application/json" }, credentials: 'include' });
if (!response.ok) {
throw new Error("Fetch is not");
}
const resData = await response.json();
console.log(resData)
}
logout을 할떄도 credentials: 'include' 설정을 해서 쿠키값을 삭제해준다
#nest.js
@Get('logout')
async logout(@Session() session: Record<string, any>, @Res() response: Response) {
return new Promise<void>((resolve, reject) => {
session.destroy((err) => {
if (err) {
response.status(500).json({ message: 'Logout failed' });
reject(err);
} else {
response.clearCookie('connect.sid'); // 세션 쿠키 삭제
response.status(200).json({ message: 'Logged out successfully' });
resolve();
}
});
});
}
1.session.destroy() 메서드:
이 메서드는 현재 세션을 파괴합니다.
세션 저장소에서 해당 세션 데이터를 삭제합니다.
2.Promise 사용:
session.destroy()는 콜백 기반이므로, Promise로 감싸 비동기 처리를 합니다.
성공 시 resolve(), 실패 시 reject(err)를 호출합니다.
3.쿠키 처리:
session.destroy()는 세션 데이터만 삭제하고, 직접적으로 클라이언트의 쿠키를 삭제하지 않습니다.
그러나 express-session 미들웨어는 보통 이 작업 후 자동으로 세션 ID 쿠키를 무효화합니다.