[Spring] Web Service의 인증과 Spring Security
Web Service의 인증
웹 인증(Web Authentication)이란 웹 애플리케이션에서 사용자의 정체성 즉 이사람이 누구인지를 확인하고 적절한 권한을 부여하는 과정이다. 따라서 웹 인증의 핵심은 사용자가 누구인지 확인하고 해당 사용자가 액세스하려는 웹 리소스나 서비스에 대한 권한이 있는지 확인하는데 사용된다.
웹 인증은 웹 서비스의 보안성을 높이며 사용자의 데이터에 무단으로 접근하는 것을 방지하기 위한 보안 요소이다.
관리자만 접근해야하는 메뉴에 아무나 접근하지 못하도록 하는 것도, A라는 유저의 데이터를 B라는 유저가 접근해서 볼 수 없도록 만드는 것도 웹의 인증과 접근 권한에 해당된다.
Spring Security의 인증과 인가
인증과 인가
- 인증: 사용자의 신원을 입증하는 과정, 사용자가 사이트에 로그인을 할 때 누구인지 확인 하는 과정
- 인가: 사이트의 특정 부분에 접근할 수 있는지 권하을 확인하는 작업
스프링 시큐리티를 사용하면 인증과 인가 관련코드를 비교적 아주 쉽게 처리할 수 있다는 장점이 있다.
Spring Security
스프링 시큐리티는 스프링 기반의 애플리케이션 보안(인증, 인가, 권한)을 담당하는 스프링 하위 프레임워크이다.
보안 관련 옵션을 많이 제공하며 애너테이션으로 설정도 매우 쉽다. CSRF 공격, 세션 고정 공격을 방어해주고 요청 헤더도 보안처리를 해주므로 개발자가 보안 관련 개발을 해야하는 부담을 크게 줄여준다.
- CSRF 공격: 사용자의 권한을 가지고 특정 동작을 수행하도록 유도하는 공격
- 세션 고정 공격: 사용자의 인증 정보를 탈취하거나 변조하는 공격
Spring Security는 웹 서비스 인증의 개념과 직접적으로 연관 되면 다음과 같은 흐름으로 동작한다.
- 사용자 등록: Spring Security는 사용자 등록 자체를 처리하는 기능을 제공하지 않지만, 등록된 사용자를 AuthenticationManager가 관리하며, 사용자 정보는 UserDetailsService에서 로드된다.
- 사용자 인증: 로그인 시 사용자 인증을 위해 UsernamePasswordAuthenticationFilter와 같은 필터를 사용하여, HTTP 요청에서 로그인 폼의 ID와 패스워드를 받아 인증을 시도한다.
- 이때 사용자가 입력한 ID와 패스워드를 UserDetailsService로 전달하여 DB에서 사용자 정보를 조회하고 PasswordEncoder로 패스워드를 검증한다.
- 인증이 성공하면 사용자 정보가 Authentication 객체에 담기고 SecurityContextHolder에 저장된다.
- 세션 관리: 사용자가 로그인한 후, Spring Security는 세션을 생성하고, 이를 통해 사용자의 인증 상태를 유지한다. 이를 통해 서버는 세션을 관리하며, 클라이언트는 세션 ID를 쿠키를 통해 전달받아 세션이 유효한 동안 인증 상태를 유지할 수 있다.
HTTP SESSION은 웹 어플리케이션에서 사용자 정보를 저장하는 기술이다. 사용자의 세션은 웹 어플리케이션에 접속한 후 일정 시간동안 유지되는 정보이다. 보통 웹브라우저 도는 연결된 커넥션이 유지되는 동안만 사용될 수 있도록 설정한다. 웹 어플리케이션에서 사용하는 인증 방법이기 때문에 안드로이드라든지 iOS 즉 네이티브 어플리케이션에서는 이 방법을 사용할 수 없다.
- HTTP 프로토콜은 Stateless한 특성을 가지기 때문에 사용자가 다시 요청을 보낼 때마다 사용자 정보를 매번 다시 전송해야한다. HTTP 세션은 이런한 문제를 해결하기 위해 사용자 정보를 서버측에서 저장하고 관리하는 세션 ID를 발급한다.
- HTTP 세션은 쿠키를 사용하여 구현된다: 서버 개발자 입장에서는 HTTP 세션이지만 클라이언트 개발자 입장에서는 그저 쿠키이기 때문에 쿠키 세션이라고도 함
- HTTP 세션은 사용자 로그인 정보를 관리할 때 사용하며 사용자가 다시 접속하여도 유지된다.
- HTTP 세션은 서버에서 관리되기 때문에 사용자가 임의로 세션 정보를 조작할 수 없다.
쿠키의 만료 기간을 정하게 되는데 보통은 연결된 세션 타임동안만 사용되도록 설정한다. 다라서 브라주러르 다든다는지 또는 연결을 끊게 되거나 서버에서 관리하기 때문에 서버가 새로 고침을 하게되면 사용자가 연결된 정보가 사라지게 된다.
HTTP 세션 인증은 서버 측에서 유지하고 관리하기 때문에 사용자가 임의로 세션 정보를 조작할 수 없다는 것이다.
- 사용자가 로그인을 시도
- 서버는 사용자의 인증 정보를 검증하여 session id를 생성
- 세션은 서버측에서 관리되며 서버에서 갱신 및 정보를 변경할 수 있다.
- 세션ID는 쿠키(cookie)방식으로 사용자에게 전달되며 웹 어플리케이션에서 사용한다.
웹 어플리케이션, 웹 브라우저에서 사용되는 형태라는 점. 안드로이드라든지 아이폰의 경우 브라우저 형식이 아니라 REST API를 쓴다. 이 때 많이 쓰는 것이 REST 클라이언트를 쓸 때는 쿠키를 실어서 보내지 않기 때문에 HTTP 세션 인증 방식을 사용하지 않는다. 보통 웹뷰어 형식이나 웹앱같은 곳에서 HTTP 세션 인증 방식을 사용한다.
Spring Security와 HTTP 세션 인증의 관계
HTTP 세션 인증은 서버가 사용자의 인증 상태를 서버 측 세션에 저장하고 관리하는 방식
Spring Security는 기본적으로 HTTP 세션 인증을 사용하여, 사용자가 인증을 완료한 후에도 로그인 상태를 유지하고 사용자가 다른 요청을 할 때마다 인증된 사용자로 인식하게 한다.
Spring Security에서의 HTTP 세션 인증 흐름
- 로그인 요청: 사용자가 로그인 폼에 ID와 비밀번호를 입력하여 로그인 요청을 보낸다.
- 인증 처리: AuthenticationManager와 같은 Spring Security의 인증 매니저는 사용자의 자격 증명을 확인하고, 성공하면 인증 토큰을 생성한다.
- 세션 생성: 인증이 성공하면 Spring Security는 새로운 세션을 생성하고, 사용자의 인증 정보를 이 세션에 저장합니다. 세션은 서버에서 유지되며 사용자의 인증 상태를 관리한다.
- 세션 ID 발급: 서버는 세션 ID를 생성하고, 이를 쿠키 형태로 클라이언트에 전달합니다. 이후 사용자는 요청 시마다 세션 ID를 서버에 전달하여 인증 상태를 유지한다.
- 세션 ID 검증: Spring Security는 각 요청마다 세션 ID를 확인하고, 세션에 저장된 인증 정보를 기반으로 사용자의 권한을 검증한다.
Spring Security에서 HTTP 세션 인증의 주요 기능
- 세션 고정 방지(Session Fixation Protection): Spring Security는 세션 고정 공격을 방지하기 위해 로그인 시 새로운 세션을 생성합니다. 이를 통해 인증 후에도 안전한 세션을 유지할 수 있다.
- 세션 만료 관리: 세션의 만료 시간을 설정할 수 있으며, 일정 시간이 지나면 세션이 만료되어 사용자가 자동 로그아웃된다.
- 세션 제한(Session Limiting): Spring Security는 한 번에 허용할 수 있는 세션의 개수를 제한할 수 있으며, 예를 들어 한 사용자가 한 번에 하나의 세션만을 유지하도록 설정할 수 있다.
세션 인증도 세션의 아이디를 쿠키로 전달하지만 서버에서 아이디만 발행하고 해당 값을 관리하는 방식이다. 따라서 서버가 멀티 서버로 돌아가는 경우 각각 서블릿에 맞춰서 세션을 동일하게 만들어주는 기술이 필요하다.
설명하자면 1, 2, 3번 서버가 있고 Nginx와 같은 웹서버를 두고 로드 벨런싱을 할 때 사용자가 접속을 요청하면 1,2,3번 서버가 같은 코드를 띄워두고 로드 밸런싱을 통해 각각 요청하게 된다.
세션의 경우 1번에 요청 시, 1번에 맺어진다. 세션ID를 가지고 로드 밸런싱이기 때문에 그 다음번에 요청햇을 때 1번으로 가지않고 2번으로 연결이 된다면 2번은 사용자가 누군지 모르기 때문에 세션을 새로 맺게 되고 이 현상은 3번도 동일하다.
이러한 현상을 방지하기 위해서 제일 많이 사용하는 것이 Redis를 통한 세션 관리(세션 클러스터링)이다.
세션 클러스터링: 2대 이상의 WAS 도는 서버를 사용할 때 로드 밸런싱, 장애 대비 등 세션을 공유(관리)하는 것
사용자가 1번 서버에 요청을 하면 redis에 세션이 하나 물리게 된다. 다른 서버로 가더라도 개별적인 세션이 아니라 redis에 들어있는 세션을 찾아서 사용자를 찾아주는 형태로 작동한다.
이렇게 되면 redis를 또 따로 운영해야하는 불편함이 있는데 이러한 부분을 보완할 수 있는 방법이 Cookie를 통한 인증이다.
HTTP Cookie 인증은 웹 브라우저에서 이루어진다는 점이 제일 중요하다. 웹 블어우저와 웹 서버간에 상태 정보를 유지하기 위한 기술이다.
서버 브라우저 즉 클라이언트의 브라우저가 자신의 로컬에 해당 쿠키 값을 저장하고 해당 쿠키를 가진 서버로 데이터가 전송되는 방식이다.(필요할 때마다 서버에 전송) 즉 저장소가 클라이언트 인것이다. 세션 인증은 서버에서 사용자의 정보를 저장하고 아이디만 줬다면 클라이언트는 자신많은 저장 공간에 해당 데이터를 저장하고 유지한다.
쿠키는 HTTP 헤더에 Set-Cookie와 같은 헤더를 통해 서버에서 클라이언트로 전송된다. Set-Cookie 헤더를 받게 되면 클라이언트 브라우저는 자신의 브라우저 저장소에다가 쿠키를 저장한다. 쿠키는 키-값 쌍으로 이루어져 있으며, 이름, 값, 유효시간, 도메인, 경로 등의 정보를 포함한다.
- 쿠키는 클라이언트 측에 저장된다. 따라서 서버가 클라이언트의 상태 정보를 확인하려면, 쿠키를 클라이언트에서 전송받아야 한다.
- 쿠키는 유효 기간을 가지고 있습니다. 유효 기간이 지나면 쿠키는 삭제된다.
- 쿠키는 보안 문제가 있을 수 있다. 쿠키에 민감한 정보를 저장하는 경우 HTTPS와 같은 보안 프로토콜을 사용하여 암호화해야한다. (보통 쿠키에 민감한 정보를 저장하지 않음)
- 쿠키는 브라우저에서 관리되기 때문에, 브라우저에서 쿠키를 삭제하거나 다른 브라우저에서 접속하는 경웨는 쿠키를 공유할 수 없다.
쿠키를 통한 인증은 현재도 많은 곳에서 사용하고 있다. 다만 쿠키를 조금 으용해서 보안 족으로 문제가 없도록 사용하며, 세션보다는 관리를 좀 더 편하게 하는 방법을 많이 사용한다.
- 사용자가 로그인 페이지에 접속하여 로그인 정보를 입력
- 서버는 사요자 정보를 검증하고, 인증이 성공하면 사용자의 고유 Id와 함께 인증 토큰(쿠키)를 생성한다.
- 서버는 생성된 인증 토큰(쿠키)을 HTTP 응답 헤더에 포함하여 클라이언트에게 전송한다.
- 클라이언트는 전송받은 인증 토큰(쿠키)을 로컬에 저장한다.
- 클라이언트는 이후 서버에 요청을 보낼 때마다 인증 토큰(쿠키)을 HTTP 요청 헤더에 포함하여 전송한다.
- 서버는 전송받은 인증 토큰(쿠키)을 검증하여 인증이 성공하면 요청에 대한 응답을 생성한다.
Spring Security와 쿠키 기반 인증의 관계
쿠키 기반 인증은 사용자 인증 정보를 클라이언트 측에 쿠키로 저장하고, 이후 클라이언트가 서버에 요청을 보낼 때마다 쿠키를 사용하여 인증을 처리하는 방식이다. 쿠키 기반 인증은 주로 RESTful API에서 많이 사용되며, 서버가 상태를 유지하지 않고 클라이언트 측에서 인증 상태를 관리하는 데 효과적이다.
Spring Security에서의 쿠키 기반 인증 흐름
- 로그인 시도: 사용자가 로그인 폼에 ID와 비밀번호를 입력하고, 서버로 로그인 요청을 보낸다.
- 인증 성공 시 쿠키 발급: 인증이 성공하면, 서버는 JWT 또는 세션 ID와 같은 인증 토큰을 생성하여 클라이언트에 전달합니다. 이 토큰은 쿠키에 저장된다.
- 쿠키 저장: 클라이언트는 전달받은 인증 토큰을 브라우저의 쿠키 저장소에 저장합니다. 이후 모든 요청 시 이 쿠키가 자동으로 서버로 전송된다.
- 쿠키 검증: 서버는 요청을 받을 때마다 쿠키에 포함된 인증 토큰을 검증하여 사용자의 인증 상태를 확인한다.
- 인증 상태 유지: 클라이언트가 보낸 쿠키를 통해 서버는 사용자의 인증 정보를 확인하고, 인증된 사용자임을 확인한 후 요청을 처리한다.
Spring Security에서 쿠키 기반 인증의 주요 특징
- JWT (JSON Web Token): 쿠키에 JWT를 저장하여 사용자의 인증 정보를 관리할 수 있습니다. JWT는 서명된 토큰이므로 클라이언트와 서버 간 인증 정보를 안전하게 주고받을 수 있다.
- 쿠키 보안 설정: Spring Security는 Secure 및 HttpOnly 플래그를 설정하여 쿠키의 보안을 강화할 수 있습니다. 이를 통해 쿠키가 자바스크립트로 접근되지 않도록 하거나 HTTPS에서만 전송되도록 설정할 수 있다.
Spring Security에서 HTTP 세션 인증과 쿠키 인증의 차이점
두 방식 모두 사용자의 인증 상태를 유지하는 데 사용되지만, 세션 기반 인증과 쿠키 기반 인증의 차이점은 다음과 같다.
구분 | HTTP 세션 인증 | Cookie 기반 인증 |
저장 위치 | 서버 측에서 세션 정보를 저장하고 관리 | 클라이언트(브라우저)에 쿠키 형태로 저장 |
상태 관리 | 서버가 상태를 유지함(Stateful) | 서버는 상태를 유지하지 않음(Stateless) |
보안성 | 서버에서 관리하므로 사용자가 세션 정보를 조작할 수 없음 | 쿠키가 탈취되면 보안 문제가 발생할 수 있음 |
확장성 | 서버 자원을 소모하여 확장성에 제약이 있음 | 서버 자원을 소모하지 않아 확장성이 좋음 |
주요 사용 사례 | 전통적인 웹 애플리케이션에서 주로 사용 | RESTful API, 모바일 애플리케이션에서 주로 사용 |
- HTTP 세션 인증은 전통적인 웹 애플리케이션에서 매우 유용하며, 서버가 사용자 세션을 관리하고 클라이언트는 세션 ID만 전달하는 방식이다.
- 쿠키 기반 인증은 Stateless한 RESTful API와 같은 애플리케이션에서 많이 사용되며, 서버가 인증 상태를 유지하지 않고 클라이언트 측에서 관리하는 방식이다. 이는 특히 확장성과 서버 리소스 절약 측면에서 이점이 있다.