오늘 배운 것
- spring security 란?
- filter 란?
- spring security filter chain
- UsernamePasswordAuthenticationFilter
- SecurityContextHolder
- Authentication
- Spring Security 로그인 처리 과정
Spring Security 란?
- Spring Security는 프레임워크다.
- Spring Security는 Spring 서버에 필요한 인증 및 인가를 위해 많은 기능을 제공한다.
- 따라서 개발자가 인증 및 인가에 대한 코드를 직접 작성하지 않아도 된다.
- 마치 Spring 프레임워크가 웹 서버 구현에 편의 제공하는 것과 같다.
- Spring Security 프레임워크는 인증 및 인가 구현에 편의 제공하는 것이다.
Filter 란?
아래 그림은 스프링에서 필터가 어떻게 동작되는지 보여주는 그림이다.
- Spring에서 모든 호출은 DispatcherServlet을 통과한다.
- 그 이후에 각 요청을 담당하는 Controller로 분배된다.
- 이 때 각 요청에 대해 공통적으로 처리해야 할 필요가 있는 경우가 있다.
- 그래서 DispatcherServlet 이전에 단계가 필요한데 이것이 필터이다.
필터는 Web 애플리케이션에서 관리되는 영역이다.
Client로부터 오는 요청과 응답에 대해 최초, 최종 단계의 위치다.
따라서 요청과 응답의 정보 변경하거나 부가적인 기능을 추가할 수 있다.
주로 범용적으로 처리해야 하는 작업들에 활용한다.
예를 들어 로깅, 보안 처리, 인증 및 인가 처리 등을 할 수 있다.
필터를 사용하면 이런 로직들을 비즈니스 로직과 분리해 관리할 수 있다는 장점이 있다.
그리고 필터는 한 개만 존재하는 것이 아니라 여러 개가 chain 형식으로 되어 있어서 처리되고 있다.
Spring Security Filter Chain
Spring Security도 인증 및 인가를 처리하기 위해 Filter를 사용한다.
Spring Security는 FilterChainProxy를 통해 상세 로직을 구현한다.
무슨 의미인가 하면 Filter들 사이에 FilterChainProxy라는 것을 만들고 따로 Security Filter Chain을 뽑아서 실행이 된다.
Security Filter Chain에는 Security Filter들이 여러 개 있고 chain 형식으로 처리되는 것이다.
UsernamePasswordAuthenticationFilter
- 로그인 처리할 때 가장 많이 사용하는 것이 로그인 창에 id (=username), password를 입력해 인증하는 것이다.
- 이때 로그인 창은 form으로 이런 로그인 방식을 form login이라고 한다.
- Spring Security에서 이런 form login을 사용한다고 설정할 수 있다.
- 이렇게 설정하면 Spring Security Filter 중에 UsernamePasswordAuthenticationFilter를 사용하게 된다.
이 UsernamePasswordAuthenticationFilter에서는 어떻게 인증을 진행하는지 과정을 보자.
인증 과정
- 사용자가 username, password를 form으로 제출한다.
- UsernamePasswordAuthenticationFilter는 UsernamePasswordAuthenticationToken 만든다.
- UsernamePasswordAuthenticationToken는 Authentication의 종류 중 하나이다.
- Authentication은 인증된 사용자의 정보가 담기는 인증 객체다.
- 즉 UsernamePasswordAuthenticationToken = 인증된 사용자의 정보가 담기는 인증 객체
- 만든 UsernamePasswordAuthenticationToken를 AuthenticationManager에게 넘겨 인증 시도한다.
- 인증에 실패하면 SecurityContextHoler를 비운다.
- 인증에 성공하면 SecurityContextHoler에 Authentication을 설정한다.
- 여기에서 Authentication은 UsernamePasswordAuthenticationToken이다.
- SecurityContextHoler에 Authentication을 설정하면 인증 처리가 완료된 것이다.
보면 아주 머리 아픈 단어들이 많이 나온다.
길이도 아주 길어서 정신이 없다.
이 중에서 SecurityContextHolder, Authentication에 대해서 알아보자.
SecurityContextHolder
위의 인증과정에서 아래와 같은 과정을 거쳤다.
- 인증에 실패하면 SecurityContextHoler를 비운다.
- 인증에 성공하면 SecurityContextHoler에 Authentication을 설정한다.
여기에서 중요해 보이는 SecurityContextHolder는 보안 정보 중앙 저장소다.
Spring Security는 보안 정보를 여러 곳에서 사용할 수 있어야 한다.
그렇기 때문에, 이를 관리하는 중앙 저장소로 SecurityContextHolder를 제공하는 것이다.
SecurityContextHolder는 아래와 같이 생겼다.
SecurityContextHolder 안에 SecurityContext가 있고 SecurityContext 안에 Authentication이 있는 형태이다.
SecurityContext는 인증이 완료된 사용자의 Authentication을 저장하는 것이다.
이런 과정으로 Authentication을 넣는 것 자체가 Security 내부적으로 인증 완료되었다는 의미이다.
Authentication
Authentication은 현재 인증된 사용자를 나타낸다.
Authentication은 SecurityContext에서 가져올 수 있다.
Authentication에는 3가지가 있다.
- principal
- credentials
- authorities
각각에 대해서 보면 아래와 같다.
principal
- 사용자를 식별하는 것이다.
- Username, Password 방식으로 인증할 때 일반적으로 UserDetails 인스턴스가 principal이다.
credentials
- 주로 비밀번호이다.
- 대부분 사용자 인증에 사용한 후 비운다.
authorities
- 사용자에게 부여하는 권한을 GrantedAuthority로 추상화 해서 사용한다.
- 이것이 있는 이유는 Security에서 제공하는 권한 기능에 사용된다.
- 권한에 따라 요청 허락하는지 안하는지 쉽게 처리하는 방법이 Security에 있다.
Authentication의 구현체가 UsernamePasswordAuthenticationToken이다.
그리고 Authentication 안에 있는 principal의 구현체가 UserDetails이다.
UserDetails는 UsernamePasswordAuthenticationToken 만들 때 사용된다.
그리고 이 UsernamePasswordAuthenticationToken은 SecurityContextHolder에 설정되는 것이다.
UserDetailsService는 Username, Password 인증 방식을 사용할 때 사용자를 조회하고 검증한 다음 UserDetails를 반환한다.
우리 DB에 있는 User를 가지고 로그인 구현하려면 UserDetailsService와 UserDetails를 커스텀해야 한다.
커스텀하지 않으면 Spring Security의 기본 username은 user이고 password는 로그로 나타난다.
이것들 가지고 로그인을 하면 된다.
Spring Security 로그인 처리 과정
Spring Security를 사용하면 Client의 요청은 모두 Spring Security를 거친다.
Spring Security에서 인증 처리 하면 Client의 요청과 UserDetails를 Controller에게 넘겨준다.
Spring Security에서 인증 실패하면 로그인 페이지를 Client에게 반환한다.
그렇다면 Spring Security에서 인증 처리는 어떻게 일어나는지 알아보자.
로그인 처리 과정을 보면 AuthenticationManager가 인증 처리한다.
- 이때 AuthenticationManager가 UserDetailsService에게 username을 넘긴다.
- 그러면 UserDetailsService에서 username을 가지고 User를 조회한다.
- 위에서 말했듯이 UserDetailsService를 커스텀해서 우리 DB에서 username 가지고 User 가져오도록 해야 한다.
- 조회해온 User 정보로 UserDetailsService가 UserDetails 객체를 만들고 AuthenticationManager로 반환한다.
- 그러면 AuthenticationManager는 UserDetails에 있는 username, password와 Client가 로그인 시도한 username, password와 비교해 인증 처리하는 것이다.
- username, password가 일치하면 로그인 성공으로 세션을 생성한다.
- username, password가 불일치하면 에러가 발생한다.
여기에서 Spring Security의 기본적인 로그인 방법은 session 방법임을 알 수 있다.
위의 AuthenticationManager에서 로그인 성공하면 인증 성공으로 UsernamePasswordAuthenticationToken에 UserDetailsService에서 받아온 UserDetails 넣고 SecurityContextHolder에 넣는 것이다.
'TIL' 카테고리의 다른 글
24.09.04 TIL - Bean Validation (0) | 2024.09.08 |
---|---|
24.09.03 TIL - Spring Security Login with JWT (0) | 2024.09.08 |
24.08.28 - JWT in Spring (6) | 2024.08.30 |
24.08.27 TIL - JWT (0) | 2024.08.28 |
24.08.26 TIL - 발생 가능 장애 (1) | 2024.08.27 |