스프링에서는 인증, 권한 등 보안에 관한 기능을 제공하는 프레임워크인 스프링 시큐리티(Spring Security) 가 있다.
우선 스프링 시큐리티(Spring Security)를 알기 전에 인증과 권한에 대해서 알아보려한다.
📌 인증(Authentication)
인증(Authentication)이란 보호된 리소스에 접근하는 대상, 즉 사용자에게 적절한 접근 권한이 있는지 확인하는 일련의 과정이다.
이 때 보호된 리소스에 접근하는 대상(사용자)을 접근 주체(Principal)이라고 한다.
📌 권한(Authorization)
권한(Authorization)이란 인증절차가 끝난 접근 주체(Principal)가 보호된 리소스에 접근 가능한지를 결정하는 것을 의미한다.
이 때 권한을 부여하는 작업을 인가(Authorize)라고 한다.
1️⃣ 스프링 시큐리티(Spring Security)의 구조
스프링 시큐리티(Spring Security)는 주로 서블릿 필터와 이들로 구성된 필터체인을 사용하고 있다.
위 그림의 동작 플로우를 간단하게 설명하면 다음과 같다.
1. Http Request = 사용자가 로그인 정보와 함께 인증을 요청
2. Authentication Filter가 요청을 가로챈 후 이 정보를 통하여 UsemamePasswordAuthentication Token이라는 인증용 객체 생성
3. Authentication Manager의 구현체인 ProviderManager에게 UsemamePasswordAuthentication Token 객체를 전달
4. 다시 Authentication Provider에게 UsemamePasswordAuthentication Token 객체 전달
5. 실제 데이터베이스에서 사용자 인증정보를 가져오는 UserDetailsService에 사용자 정보(아이디)를 전달
6. 넘겨받은 사용자 정보를 통해 DB에서 찾은 사용자 정보인 UserDetails 객체를 생성, 이 때 UserDetails는 인증용 객체와 도메인용 객체를 분리하지 않고 인증용 객체에 상속해서 사용하기도 한다
7. Authentication Provider는 UserDetails를 넘겨 받고 사용자 정보를 비교
8. 인증이 완료되면 권한 등의 사용자 정보를 담은 Authentication 객체를 반환
9. 다시 최초의 Authentication Filter에 Authentication 객체를 반환
10. Authentication 객체를 SecurityContext에 저장
결론은, SecurityContextHolder는 세션 영역에 있는 SecurityContext에 Authentication 객체를 저장한다.
세션에 사용자 정보를 저장한다는 것은 스프링 시큐리티(Spring Security)가 전통적인 세션, 쿠키 기반의 인증 방식을 사용한다는 것을 의미한다.
Spring SecurityFiter는 매우 많은 필터를 가지고 있다. 모두 외울 필요는 없지만 대략적인 내용을 이해하고 있으면 필터를 사용할 때 많은 도움이 될 것이다.
Security의 Filter의 종류
- HeaderWriterFilter : Request의 Http 해더를 검사하여 header를 추가하거나 빼주는 역할을 한다.
- CorsFilter : 허가된 사이트나 클라이언트의 요청인지 검사하는 역할을 한다.
- CsrfFilter : Post나 Put과 같이 리소스를 변경하는 요청의 경우 내가 내보냈던 리소스에서 올라온 요청인지 확인한다.
- LogoutFilter : Request가 로그아웃하겠다고 하는것인지 체크한다.
- UsernamePasswordAuthenticationFilter : username / password 로 로그인을 하려고 하는지 체크하여 승인이 되면 Authentication을 부여하고 이동 할 페이지로 이동한다.
- ConcurrentSessionFilter : 동시 접속을 허용할지 체크한다.
- BearerTokenAuthenticationFilter : Authorization 해더에 Bearer 토큰을 인증해주는 역할을 한다.
- BasicAuthenticationFilter : Authorization 해더에 Basic 토큰을 인증해주는 역할을 한다.
- RequestCacheAwareFilter : request한 내용을 다음에 필요할 수 있어서 Cache에 담아주는 역할을 한다. 다음 Request가 오면 이전의 Cache값을 줄 수 있다.
- SecurityContextHolderAwareRequestFilter : 보안 관련 Servlet 3 스펙을 지원하기 위한 필터라고 한다.
- RememberMeAuthenticationFilter : 아직 Authentication 인증이 안된 경우라면 RememberMe 쿠키를 검사해서 인증 처리해준다.
- AnonymousAuthenticationFilter : 앞선 필터를 통해 인증이 아직도 안되었으면 해당 유저는 익명 사용자라고 Authentication을 정해주는 역할을 한다. (Authentication이 Null인 것을 방지!!)
- SessionManagementFilter : 서버에서 지정한 세션정책에 맞게 사용자가 사용하고 있는지 검사하는 역할을 한다.
- ExcpetionTranslationFilter : 해당 필터 이후에 인증이나 권한 예외가 발생하면 해당 필터가 처리를 해준다.
- FilterSecurityInterceptor : 사용자가 요청한 request에 들어가고 결과를 리턴해도 되는 권한(Authorization)이 있는지를 체크한다. 해당 필터에서 권한이 없다는 결과가 나온다면 위의 ExcpetionTranslationFilter필터에서 Exception을 처리해준다.
참고 : https://velog.io/@seongwon97/Spring-Security-Filter%EB%9E%80
2️⃣ JWT(Json Web Token)
JWT(Json Web Token)은 Json 객체를 통해 안전하게 정보를 전송할 수 있는 웹표준(RFC7519)이다. JWT는 " . " 를 구분자로 세 부분으로 구분되어 있는 문자열로 이루어져있다. 각각 헤더는 토큰 타입과 해상 알고리즘을 저장하고, 내용은 실제로 전달할 정보, 서명에는 위조변조를 방지하기 위한 값이 들어간다.
JWT는 JSON 객체를 암호화 하여 만든 문자열 값으로 위, 변조가 어려운 정보라고 할 수 있다. 그리고 다른 토큰들과 달리 토큰 자체에 데이터를 가지고 있다는 특징이 있다.
JWT의 이러한 특징 때문에 사용자의 인증 요청시 필요한 정보를 전달하는 객체로 사용할 수 있다.
API서버는 로그인 요청이 완료되면 클라이언트에게 회원을 구분할 수 있는 정보를 담은 JWT를 생성하여 전달한다.
그러면 클라이언트는 이 JWT를 헤더에 담아서 요청을 하게 된다. 권한이 필요한 요청이 있을 때 마다 API서버는 헤더에 담긴 JWT 값을 확인하고 권한이 있는 사용자 인지를 확인 한 후 리소스를 제공하게 된다.
이렇게 기존의 세션, 쿠기 기반의 로그인이 아니라 JWT같은 토큰 기반의 로그인을 하게 되면 세션이 유지되지 않는 다중 서버 환경에서도 로그인을 유지할수 있게 되고 한 번의 로그인으로 유저정보를 공유하는 여러 도메인에서 사용할 수 있다는 장점이 있다.
이 때 회원을 구분할 수 있는 정보가 담긴 곳이 바로 JWT의 Payload 부분이고 이곳에 담기는 한 조각을 Claim이라고 한다.
Claim은 name/value 한 쌍으로 이루어져 있으며 당연히 여러개의 Claim 들을 넣을 수 있다.
참고 사이트:https://webfirewood.tistory.com/115
'Back-end > spring' 카테고리의 다른 글
[Spring] DI, IoC 정리 (0) | 2022.11.14 |
---|---|
[Spring] Spring Bean의 개념과 Bean Scope의 종류 (0) | 2022.11.14 |
[Spring] Lombok 어노테이션 정리 (1) | 2022.11.14 |
[Spring JPA] JPA는 무엇인가? (0) | 2022.09.23 |
Spring 공부 -프롤로그 (0) | 2022.02.09 |