[Security] SecurityContext의 사용자 인증 정보 가져오기

손은실·2024년 8월 20일
0

Spring Boot

목록 보기
3/13
post-thumbnail

이슈 배경

Spring Security 폼 로그인을 통해 사용자 인증을 수행했습니다.
로그인에 성공한 사용자의 정보는 Spring Security에 의해 별도의 저장소에 보관됩니다.

그러나, Spring Security가 사용자의 정보를 가지고 있음에도 불구하고, Controller에서 username을 파라미터로 받고 있었습니다. 다른 사용자가 타인의 계정을 입력하면 타인의 정보를 모두 조회할 수 있는 위험한 로직이었습니다.

클라이언트에게 username을 받지 않고, Spring Security가 가지고 있는 사용자의 인증 정보를 가져오도록 변경했습니다.



❓ 인증된 유저의 정보가 저장되는 과정

폼 로그인에 성공한 유저의 정보는 UserDetailService를 구현한 클래스에서 유저 정보 반환 메소드를 가진 UserDetails 객체로 만들어집니다.

그리고, AuthenticationManager에 의해 인증 완료 객체가 생성되어 SecurityContextAuthentication 객체로 저장됩니다.


Authentication 객체에 접근하기 위해서는 아래와 같이 왼쪽에서 오른쪽 순으로 접근할 수 있습니다.

SecurityContextHolder > SecurityContext > Authentication

  • SecurityContextHolder: 보안 주체의 보안 컨텍스트에 대한 세부 정보
  • SecurityContext: Authentication 객체 보관 및 반환
  • Authentication: 현재 접근하는 주체의 정보와 권한



💡 인증된 유저의 정보 반환

  1. SecurityUtil 클래스를 만들어 UserDetails의 정보를 반환하는 메소드 생성
  2. 유저 정보가 필요한 서비스 레이어에서 SecurityUtil 클래스를 주입해 인증된 유저의 정보를 반환 받기



Spring Security 모듈 사용하기

개발 환경

  • Spring Boot 3
  • Java 17
  • Spring Security

해당 포스팅의 실제 코드는 EunsilSon - BookMarky에서 확인할 수 있습니다.


🟢 SecurityUtil

SecurityContextHolder를 import 받고, SecurityContextHolder의 context의 Authentication을 가져옵니다.

authentication.getPrincipal() instanceof UserDetails userDetails
  • 인증된 유저의 주체(principal)의 반환 값이 UserDetails이라면 userDetails라는 변수에 할당
  • instanceof: 객체가 특정 클래스나 인터페이스의 인스턴스인지에 대한 여부 확인

    위와 같은 패턴 매칭 코드는 Java 16 이상 사용 가능




🟢 Service

아래의 코드는 특정 사용자가 저장한 정보를 불러오는 메소드입니다.
username을 파라미터로 받지 않고, SecurityUtil의 메소드를 호출해 반환받고 있습니다.


❓ 어떻게 사용자를 구분할까

  • Spring Security 폼 로그인에 성공하면, Security 세션에 사용자의 정보가 저장됩니다.
  • 여러 명의 사용자가 인증에 성공하면, 여러 개의 세션이 저장되게 됩니다.
  • 여러 명의 사용자들이 동시 접속하여 본인의 username을 조회할 때 어떻게 구분할까요?

자동으로 세션 ID를 주고 받으며 사용자를 구분하게 됩니다.


세션 ID 전달

  • 인증에 성공한 클라이언트에게 헤더에 세션 ID를 포함하여 전달합니다.
  • 이는 자동으로 전달되므로 별도의 설정이 필요하지 않습니다.

[브라우저의 Response Header]


세션 ID를 브라우저의 쿠키로 저장

  • 서버로부터 받은 세션 ID를 브라우저가 자동으로 쿠키에 저장합니다.
  • 이후, 동일한 도메인의 서버에 요청을 보낼 때 저장된 세션 ID를 자동으로 담아 요청 메세지와 함께 전달합니다.
  • 이또한 자동으로 전달되므로 별도의 설정이 필요하지 않습니다.

[브라우저의 Request Header]

Response Header와 Request Header의 쿠키가 동일한 것을 확인할 수 있습니다.

0개의 댓글