CS

[CS] SpringSecurity(feat. ChatGPT)

처누 2024. 12. 20. 18:53

ChatGPT와 함께하는 면접 준비

 

질문 2: Spring Security 관련 질문

 

1. Spring Security에서 사용자의 인증 정보를 처리하는 Authentication 객체와 SecurityContext의 역할과 작동 방식을 간단히 설명해 주세요.

 

내 답변

더보기

Authentication 객체는 인증된 사용자 정보를 저장하는 역할입니다. 사용자가 로그인을 진행 시 Authentication 객체에 저장하고, 이후 인증된 사용자 정보를 사용할 때 SecurityContext에 Authentication 객체 정보를 넘깁니다. 


정리

  • Authentication
    - 인증에 성공하면 사용자 정보를 담고 있는 Authentication 객체가 생성됨.
    - 이 객체는 Spring Security의 SecurityContext에 저장되어 이후 요청에서 사용됨.
  • AuthenticationManager
    - 인증을 처리하는 핵심 컴포넌트
    - 입력된 사용자 자격 증명(사용자명, 비밀번호)을 기반으로 인증 여부를 결정함.
  • AuthenticationProvider
    - 실제 인증 로직을 처리하는 구성 요소
    - 사용자 자격 증명을 확인하고, 인증 성공 시 Authentication 객체를 반환
  • UserDetailsService
    - 사용자 정보를 로드하는 서비스
    - 주로 데이터베이스에서 사용자를 검색하여 인증에 필요한 정보를 제공함.
  • SecurityContext
    - 현재 인증된 사용자 정보를 저장하는 컨텍스트
    - Spring Security는 HTTP 요청 간 인증 상태를 유지하기 위해 SecurityContext를 사용한다.
    - ThreadLocal에 저장되어 아무 곳에서나 참조가 가능하도록 설계함.
    - 인증이 완료되면 HttpSession에 저장되어 애플리케이션 전반에 걸쳐 전역적인 참조가 가능함.

 

Spring Security 인증의 주요 과정

1. 사용자 요청 처리

 - 사용자가 애플리케이션에 요청(로그인 요청)을 보낸다.

2. AuthenticationManager에 인증 요청

 - AuthenticationManager가 UsernamePasswordAuthenticationToken을 생성하여 인증 요청

 - AuthenticationManager는 사용자 정보를 AuthenticationProvider로 전달하여 인증을 시도함.

 - AuthenticationProvider가 비밀번호를 검증하고, 성공 시 사용자 정보를 포함한 Authentication 정보를 반환

3. 사용자 정보 검증

 - UserDetailsService를 통해 데이터베이스 또는 외부 시스템에서 사용자 정보를 로드함.

 - 제공된 비밀번호와 저장된 비밀번호를 비교하거나 OAuth2를 통해 인증을 확인함.

4. Authentication 객체 생성

 - 인증에 성공하면 Authentication 객체를 생성하여 SecurityContext에 저장함.

5. 권한 부여

 - 인증된 사용자 요청에 대해 권한을 확인하고, 리소스 접근을 허용하거나 제한함.

 

수정된 답변

더보기

Authentication 객체의 역할은 인증에 성공한 사용자 정보를 담고, SecurityContext에 저장되어 이후 요청에서 사용됩니다. 사용자가 애플리케이션에 요청을 보내면 AuthenticationManager가 UsernamePasswordAuthenticationToken을 생성하여 AuthenticationProvier로 전달하여 인증을 시도합니다. UserDetailsService를 통해 DB 또는 외부 시스템에서 사용자 정보를 로드하고, 제공된 비밀번호와 저장된 비밀번호를 비교하거나 OAuth2를 통해 인증을 확인합니다. 인증에 성공된 Authentication 객체를 생성하여 SecurityContext에 저장합니다.

SecurityContext는 HTTP 요청 간 인증 상태를 유지하기 위한 역할을 합니다.


ChatGPT 꼬리 질문

1-1. "Authentication 객체는 인증된 사용자 정보를 저장하는 역할이며, SecurityContext에 저장된다"고 하셨는데,

  • 정확한 설명입니다. 다만 추가적으로, SecurityContext가 어디에 저장되는지, 그리고 이 저장 방식이 REST API에서 어떻게 적용되는지 간단히 말씀해 주실 수 있을까요?
  • 내 답변
더보기

SecurityContextHolder에 저장되며 Thread Local에 저장됩니다. Thread Local에 저장되어 애플리케이션 전역에서 사용 가능하므로 API 요청 시 해당 저장소에서 SecurityContext내 저장된 Authentication 객체를 호출하여 사용할 수 있습니다.


 

2. RESTful API에서는 세션을 사용하지 않는 경우가 많습니다. 이 상황에서 JWT를 사용해 인증을 구현한다고 할 때,

  • Access Token과 Refresh Token의 역할은 각각 무엇인가요?
  • 내 답변
더보기

AccessToken은 세션 대신 사용자의 권한을 유지할 수 있도록 해주는 토큰입니다. RefreshToken은 AccessToken의 갱신을 위한 토큰입니다.

  • Refresh Token이 필요한 이유는 무엇이며, 이를 어떻게 안전하게 관리할 수 있을지 설명해 보세요.
  • 내 답변
더보기

답변 : AccessToken이 탈취 당할 경우 AccessToken을 삭제 후 RefreshToken을 통해 AccessToken을 갱신합니다. 이를 안전하게 관리하기 위해 외부 저장소(Redis)를 통해 TTL을 설정하여 관리하는 방법이 있습니다.


 

정리

  • AccessToken
     - 클라이언트가 서버의 API에 접근할 수 있도록 허가된 권한을 나타내는 토큰.
     -  사용자의 인증 및 권한 검사를 위한 수단으로 사용됨.
     -  주로 클라이언트와 서버 간의 요청-응답 과정에서 사용.
     -  유출될 경우, 짧은 유효 기간 덕분에 피해를 최소화할 수 있음.
  • RefreshToken
     -  새로운 AccessToken을 발급받기 위해 사용하는 토큰
     -  AccessToken이 만료된 후, 사용자가 다시 인증 과정을 거치지 않고도 지속적으로 서비스를 이용할 수 있도록 함.
     -  보안 위험을 줄이기 위해 서버 측에서 주로 저장되며, 클라이언트에는 저장하지 않는 것이 일반적임.

동작 흐름

1. 사용자 인증(로그인)

 -  사용자가 로그인 하면 서버는 사용자 인증 정보를 확인한 뒤, AccessToken과 RefreshToken을 생성하여 클라이언트에게 반환

2. API 요청(AccessToken 사용)

 -  클라이언트는 AccessToken을 사용하여 보호된 API에 접근.

 -  서버는 AccessToken을 검증하고 요청을 처리.

3. AccessToken 만료

 -  AccessToken이 만료되면 클라이언트는 RefreshToken을 사용하여 새로운 AccessToken을 요청.

4. 토큰 갱신

 -  서버는 RefreshToken을 검증.

 -  RefreshToken이 유효하면 새로운 AccssToken을 발급하고, 필요시 RefreshToken도 갱신

5. RefreshToken 만료

 -  RefreshToken이 만료되면 사용자는 다시 로그인해야 함.

 

수정된 답변

더보기

AccessToken은 사용자가 서버에 접근할 수 있도록 허가된 권한을 나타내는 토큰입니다. RefreshToken은 새로운 AccessToken을 발급하기 위해 사용하는 토큰입니다.


ChatGPT 꼬리 질문

2-1. Access Token과 Refresh Token의 역할에 대한 설명은 정확했습니다. "Refresh Token을 Redis로 관리한다"고 하셨는데,

  • Redis에 Refresh Token을 저장할 때 TTL을 설정한다고 하셨습니다. 만약 Redis가 초기화되거나 장애가 발생할 경우, 시스템은 어떻게 대응해야 한다고 보십니까?
  • 내 답변 X
  • ChatGPT 답변 
    • 다중 노드 설정 : Redis 클러스터나 Sentinel 설정을 통해 장애 복구를 자동화.
    • 백업 및 복구 : 중요한 데이터(RefreshToken)를 주기적으로 백업하고, 복구 시 기본 정책을 설정.
    • Fallback 전략 : Redis 장애 시 RefreshToken 없이 AccessToken 만료 시 새로 로그인하도록 유도.
  • 수정된 답변
더보기

Redis 장애 발생 시 DB에 접근할 수 있도록 설계해야 한다고 생각합니다. 또한 이 과정에서 서킷 브레이커 패턴을 활용한다면 비용적 측면에서도 이점이 있다고 생각합니다.


3. JWT 기반 인증에서 발생할 수 있는 취약점이나 보안 문제를 최소화하기 위한 방법을 세 가지 제시해 주세요.

 

내 답변

더보기

JWT 기반 인증에서 발생할 수 있는 취약점은 탈취 문제라고 생각합니다. 이를 최소화하기 위한 방법으로는 첫째, 외부 저장소(Redis 등)를 통한 관리입니다. TTL을 설정하여 함께 관리한다면 일정 시간 이후 삭제되기 때문에 보안으로부터 안전할 수 있다고 생각합니다. 둘째, 토큰 생성 시 개인 정보를 최소화하여 저장하는 방법입니다. 대부분 토큰을 생성할 때 사용자에 대한 정보를 토큰에 저장하게 되고, 해당 토큰이 탈취될 경우 사용자의 정보나 권한으로 인한 보안으로 위험이 생깁니다. 사용자의 개인 정보를 최소화 한다면 보안 문제도 최소화 될 수 있다고 생각합니다.

 

수정된 답변

더보기

보안 문제를 최소화하기 위한 방법 세 가지를 제시해보겠습니다. 첫번째로, 블랙리스트를 활용하는 것입니다. 기한이 끝난 토큰 또는 사용자의 권한 변경이나 로그아웃 시 해당 토큰을 블랙리스트에 등록하여 기존의 토큰을 무효화 하는 것입니다. 두번째는 JWT 생성 시 클라이언트의 IP 주소 또는 User-Agent를 포함하여 서버 검증 시 동일한 IP 또는 user-Agent에서 요청이 오는지 확인하는 것입니다. 세번째로 토큰에 jti 필드를 추가하여 고유 식발자를 생성하여 Redis에 사용된 jti를 저장하고, 동일한 ID가 재사용되지 않도록 검증하거나 중요한 작업에는 별도의 1회용 토큰을 발급하여 사용 후 무효화 하는 방법입니다.


ChatGPT 꼬리 질문

3-1. JWT 취약점에 대한 답변에서 '탈취' 문제를 말씀하셨는데,

  1. 외부 저장소를 사용해 TTL을 설정하는 방법은 적절한 대처 방식 중 하나입니다. 다만, 보안 강화를 위해 추가적인 조치를 생각해 보셨는지 궁금합니다. 예를 들어, 탈취를 방지하기 위해 IP나 User-Agent를 기반으로 하는 클레임 추가와 같은 기법에 대해 알고 계신지요?
  2. JWT를 사용하는 경우, 탈취 외에도 Replay Attack이나 잘못된 서명 키 관리로 인해 발생하는 문제가 있을 수 있습니다. 이런 상황에 대한 대응 방안도 설명해 주실 수 있을까요?

내 답변

더보기

3-1.1. JWT 생성 시 IP 나 User-Agent를 포함하여 서버 검증 시 동인한 IP 또는 User-Agent에서 요청이 오는지 확인하는 기법에 대해 알고 있습니다.

 

3-1.2. Replay Attack에 대해서는 토큰에 jti(JWT ID) 필드를 추가하여 고유 식별자를 생성해 Redis에 사용된 jti를 저장하고, 동일한 ID가 재사용되지 않도록 검증하는 방법이 있습니다. 또는 1회용 토큰을 발급하여 사용 후 무효화 하는 방법도 있습니다. 잘못된 서명 키 관리로 인해 발생하는 문제에 대해서는 HMAC-SHA256과 같은 알고리즘을 사용하거나 AWS에서 제공하는 키 관리 시스템을 사용하는 방법이 있습니다.

+ ChatGPT 답변 : 

키를 주기적으로 교체하는 키 롤링(Key Rolling)기법