학교 공부/컴퓨터 네트워크
Session ID
wqdsdsf
2024. 7. 18. 08:21
1.세션 작동 방식
-> 세션 데이터 자체는 서버에 저장
-> 클라이언트(브라우저)에는 세션 ID가 쿠키(connect.sid)로 저장
2.세션 저장소가 아닌 왜 쿠키에 저장이 되는가?
-> 브라우저에서 쿠키를 확인하면 세션 ID가 보인다
-> 세션 데이터 자체는 서버에 저장되고 세션 ID만 클라이언트 측의 쿠키에 저장(클라이언트가 세션 데이터에 직접 접근하거나 조작할 수 없게 되어 보안이 강화)
-> 서버는 세션 ID를 통해 해당 세션 데이터를 찾아서 사용할 수 있습니다
3. 세션 저장소
-> 기본적으로는 nest.js는 메모리에 세션을 저장하기 떄문에 서버를 재시작하면 모든 세션 데이터가 사라진다.
4. 장점
-> 쿠키는 HTTP 요청에 자동으로 포함되어 전송됩니다. 클라이언트가 서버에 요청을 보낼 때마다 세션 ID를 명시적으로 포함시키지 않아도 되므로, 세션 ID를 쿠키에 저장하는 것이 더 편리합니다.
#세션을 직접 실행하기 전에
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';
#1번에 대한 설명
#일반적인 Cookie로 클라이언트에 설정했을시
1-1(사진) 사진과 같이 현재 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가 출력되는 걸 볼수있다(보안적으로 안좋다).
#세션을 이용해 세션 ID를 설정했을시
1-1(사진) 사진과 같이 현재 cookie 값에 아무것도 없는 상황이다.
#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를 사용하면 보안측면에서도 좋다.
#2번에 대한 설명
#nest.js
@Get('check-session')
checkSession(@Session() session: Record<string, any>) {
console.log('Session data:', session);
return { isLoggedIn: session.isLoggedIn || false };
}
데이터는 서버에 저장되는걸 확인하는 코드이다.
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에 저장되고 데이터는 서버에 저장된다(자동 로그인에 사용할수있다)
#4번에 대한 설명
쿠키 값을 설정하면 클라이언트에서 인증을 할때마다 코드를 추가하여서 데이터를 같이 보내야하는거 아니에요? 라는 생각이 들수있다.
#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 쿠키를 무효화합니다.