Spring Security

xyzw·2023년 7월 7일
0

Spring

목록 보기
14/22

<코드로 배우는 스프링 부트 웹 프로젝트> Chap. 10

기본 구조

핵심 역할은 Authentication Manager(인증 매니저)를 통해서 이루어진다.
Authentication Provider는 인증 매니저가 어떻게 동작해야 하는지를 결정하고 최종적으로 실제 인증은 UserDetailsService에 의해서 이루어진다.

핵심 개념

인증

자신을 증명하는 것
ex) 사용자는 은행에 가서 자신이 어떤 사람인지 자신의 신분증으로 자신을 증명한다.

인가

일종의 허가를 해주는 과정
ex) 은행에서 사용자가 금고를 열어볼 수 있는 사람인지 판단한다.

필터와 필터 체이닝

필터

스프링 시큐리티에서 서블릿이나 JSP에서 사용하는 필터와 같은 개념이고, 스프링의 빈과 연동할 수 있는 구조로 설계되어 있다.

필터 체인

스프링 시큐리티 내부에는 여러 개의 필터가 Filter Chain이라는 구조로 Request를 처리하게 된다. 개발 시에 필터를 확장하고 설정하면 스프링 시큐리티를 이용해서 다양한 형태의 로그인 처리가 가능하게 된다.

Authentication Manager

필터의 핵심 동작은 AuthenticationManager를 통해서 Authentication이라는 타입의 객체로 작업을 하게 된다. AuthenticationManager가 가진 인증 처리 메서드는 파라미터도 Authentication 타입으로 받고, 리턴 타입도 Authentication이다.

인증(Authentication)은 주민등록증과 비슷하다고 생각하면 된다.
인증이라는 용어는 '스스로 증명하다'라는 의미이다.

예를 들어 로그인하는 과정에서 사용자의 아이디/패스워드로 자신이 어떤 사람인지를 전달한다. 전달된 아이디/패스워드로 실제 사용자에 대해서 검증하는 행위는 AuthenticationManager를 통해서 이루어진다.
실제 동작에서 전달되는 파라미터는 UsernamePasswordAuthenticationToken과 같이 토큰이라는 이름으로 전달된다. 즉, 스프링 시큐리티 필터의 주요 역할이 인증 관련된 정보를 토큰이라는 객체로 만들어서 전달한다는 것이다.

기본으로 제공되는 필터 중에서 UsernamePasswordAuthenticationFilter 클래스 코드의 일부를 보자.

String username = obtainUsername(request);
username = (username != null) ? username : "";
username = username.trim();
String password = obtainPassword(request);
password = (password != null) ? password : "";
UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);
//Allow subclass to set the "datails" property
setDetails(request, authRequest);
return this.getAuthenticationManager().authenticate(authRequest);

request를 이용해서 사용자의 아이디와 패스워드를 받아서 UsernamePasswordAuthenticationToken이라는 객체를 만들고 이를 AuthenticationManager의 authenticate()에 파라미터로 전달하는 것을 볼 수 있다.

AuthenticationManager는 다양한 방식으로 인증처리 방법을 제공해야 한다. 예를 들어 데이터베이스를 이용할 것인지, 메모리 상에 있는 정보를 활용할 것인지와 같이 다양한 방법을 사용할 수 있다.
AuthenticationManager는 이러한 처리를 AuthenticationProvider로 처리한다.

AuthenticationProvider는 전달되는 토큰의 타입을 처리할 수 있는 존재인지를 확인하고, 이를 통해서 authenticate()를 수행하게 된다. 따라서 다양한 인증처리를 할 수 있는 객체들을 가지는 구조가 된다.

AuthenticationProvider는 내부적으로 UserDetailsService를 이용한다. UserDetailsService는 실제로 인증을 위한 데이터를 가져오는 역할을 한다. 예를 들어 JPA로 Repository를 제작했다면 UserDetailsService를 활용해서 사용자의 인증 정보를 처리한다.

인가(Authorization)의 권한/접근 제한

인증처리 단계가 끝나면 다음으로 '사용자의 권한이 적절한가?'에ㅔ 대한 처리가 이루어진다.
인가는 '승인'의 의미이다. 인증이 사용자가 스스로 자신을 증명하는 것이라면, 인가는 허가의 의미이다.

필터에서 호출하는 AuthenticationManager의 authenticate() 메서드는 Authentication이라는 '인증' 정보를 리턴한다. 이 인증 정보 내에는 Roles라는 '권한'에 대한 정보가 있다. 이 정보로 사용자가 원하는 작업을 할 수 있는지 '허가'하게 되는데, 이러한 행위를 'Access-control'이라고 한다. 일반적인 경우라면 설정으로 원하는 목적지에 접근 제한을 걸고, 스프링 시큐리티에 이에 맞는 인증을 처리한다.

정리

단계1. 사용자는 원하는 URL을 입력한다.

단계2. 스프링 시큐리티(필터)에서는 인증/인가가 필요하다고 판단하고 사용자가 인증하도록 로그인 화면을 보여준다.

사용자는 스스로를 인증하기 위해서 계정에 대한 정보를 입력한다.

단계3. 정보가 전달되면 AuthenticationManager가 적절한 AuthenticationProvider를 찾아서 인증을 시도한다.

AuthenticationProvider의 실제 동작은 UserDetailsService를 구현한 객체로 처리한다. 만일 올바른 사용자라고 인증되면 사용자의 정보를 Authentication 타입으로 전달한다(인증).
전달된 객체로 사용자가 적절한 권한이 있는지 확인하는 '인가' 과정을 거치게 된다.

0개의 댓글