현재 만들어 보고 있는 online judge 프로젝트의 서비스 구성은 다음과 같다.(관련 있는 2개만 표시. 실제로는 7개)

인증 서비스 (Backend): 사용자의 회원 가입, 로그인, 로그아웃, 세션 관리 등을 담당
인증 서비스 (Frontend): 사용자 인터페이스를 제공 (로그인 폼, 회원가입 폼 등)

 

한가지 알아두면 좋은점은 Spring Boot의 경우 /login, /logout endpoint의 경우 직접 정의하지 않아도 자동으로 처리한다는 점이다.(이점 때문에 디버깅시 많이 헷갈렸다ㅠ)

 

세션은 서버에서 브라우저로 set-cookie 헤더를 통해서 세션아이디를 부여한다.

아래처럼 브라우저 개발자 도구에서 확인가능하다(애플리케이션탭 > 쿠키섹션)

 

서버의 세션과 브라우저(클라이언트)의 쿠키 개념

세션을 서버에서 생성하고 세션id를 set-cookie를 통해서 브라우저(클라이언트)로 전달한다.

이때 쿠키는 브라우저를 종료해도 유지되는 지속쿠키를 쓰고 만료시점을 정의할수도 있고, 세션쿠키를 쓰면 브라우저 종료시 자동으로 쿠키도 삭제된다.

Expres/Max-Age 컬럼을 보면 세션쿠키와 지속쿠키의 차이를 볼 수 있다.

서버의 세션의 경우 지속시간을 application.properties에 다음과 같이 지정할 수 있다.

server.servlet.session.timeout=30m

현재 내가 테스트중인 프로젝트에서는 /login 성공시 세션쿠키가 발급되며, 세션 타임아웃의 효과는 확인이 안되었다.

일단은 이정도에서 더 깊이 안파고 넘어가기로 한다.

 

트러블슈팅

http에서 포트가 서로다른 서비스(MSA)간 연동하기

아래 크롬 설명에 따르면 https를 쓰고 secure 옵션을 주어야 SameSite=None으로 지정하면서 포트가 달라도 쿠키저장이 된다는것 같다.(관련글, 관련글2)

 

set-cookie로 응답을 제대로 했음에도 브라우저에 쿠키저장이 안될때

클라이언트에서 서버로 요청할때 credential을 보내줘야 했다(이것땜에 한참헤맴 ㅠ)

      const response = await axios.post('https://sevity.com:9991/login', `username=${username}&password=${password}`, {
        headers: {
          'Content-Type': 'application/x-www-form-urlencoded',
        },
        withCredentials: true,  // 여기, 이 줄 없으면 브라우저에 쿠키저장 안된다!!
      });

 

getSession(true)의 안전성

HttpSession session = request.getSession(false); 를 하면 존재하는 세션정보를 가져오고, false자리에 true를 넣으면 없으면 생성하라는 의미인데, 이렇게 하면 (내가만든세션), (SpringSecurity에 의해 아직 없지만 생성될 세션) 이렇게 두벌이 될까봐 우려했는데, 나중에 확인해보니 그렇지는 않았다. 따라서 항상 true로 호출해도 무방한 것 같다.

 

단 여기를 보면 멀티스레드 환경에서 레이스 컨디션에 의해 중복세션과 중복쿠키가 생성되는 경우는 있는 것 같다. 해결책은 아래처럼 동기화블록내에 생성과 처리를 묶어주면 되긴할듯(현재 내 구현에서는 그렇게 까지 하진 않았다)

synchronized (request) {
    HttpSession session = request.getSession(true);
    // ... 세션 사용 코드 ...
}

 

 

TMI

/login에서 반환되는 response.data 값과 SESSION쿠키의 값은 동일하나, SESSION쿠키의 경우 base64로 인코딩 되어 있다.

//response.data: c8545bb7-c90b-4d69-9128-08efd0a73866
//SESSION(쿠키): Yzg1NDViYjctYzkwYi00ZDY5LTkxMjgtMDhlZmQwYTczODY2

let encodedSessionId = 'Yzg1NDViYjctYzkwYi00ZDY5LTkxMjgtMDhlZmQwYTczODY2';
let decodedSessionId = atob(encodedSessionId);
console.log(decodedSessionId);  // 출력: c8545bb7-c90b-4d69-9128-08efd0a73866

 

반응형

+ Recent posts