
드디어 마지막 장인 13장을 다 읽었다..
Chap.13 서비스의 인증과 권한 부여
서비스를 개발하다보면, 회원간의 별도의 데이터를 저장한다던가, 특정 게시물을 삭제할 때, 요청한 유저가 해당 게시글의 주인인가를 파악하는 로직이 추가되기 마련이다. 이런 경우에 Spring Boot에서는 요청을 보낼때 누가 보냈는지를 넣어서 전달하고 반환받을 수도 있지만, 이런 것은 Spring스럽지 않기 때문에, Spring Boot Security를 사용해서 보안과 인증, 권한을 처리한다.
13.1 보안 용어 이해
인증 Authentication은 사용자가 누구인지 확인하는 단계를 의미한다. 예를 들자면 로그인과 같은 기능이 존재한다.
로그인 Form에 Username과 Password를 입력한 후 전달하고, 서버에서는 해당 데이터가 옳다면 서버에서 인증에 사용하는 방법에 맞는 반환값을 전달한다. JWT와 같은 Token 방식을 채택했을 경우, accessToken을 전달하게 될 것이다.
인가 Authorization은 이전의 인증을 통해 검증된 사용자가 특정 API에 접근할 때, 해당 권한이 있는 지 없는 지를 검사하는 과정을 의미합니다. 예를 들면, 사용자가 특정 게시판에 접근하려고 할때, 해당 유저의 권한을 확인하여 해당 게시판에 접근할 수 있는 지를 확인하고 접근을 허가하거나 거부하는 것이 대표적인 인가의 사례입니다. 인증 단계에서 받은 토큰은 Http Request의 Header 중 Authorization에 넣어서 토큰을 서버로 전달합니다.
접근 주체 principal은 말 그대로 애플리케이션의 기능을 사용하는 주체입니다. 사용자가 될 수도 있고 특정 디바이스에서 호출을 하거나, 시스템에서 사용하게 될 수도 있습니다. 애플리케이션은 앞서 소개한 인증과정을 통해 접근 주체가 신뢰할 수 있는지 확인하고, 인가 과정에서 접근 주체에게 부여된 권한을 확인하는 과정들을 거칩니다.
13.2 Spring Security
스프링 시큐리티는 인증과 인가등의 보안 기능을 제공하는 스프링 하위 프로젝트중 하나로, 보안과 관련된 많은 기능을 제공하기 때문에, 스프링 시큐리티를 활용하면 더욱 편리하게 원하는 기능을 설계할 수 있습니다.
13.3 스프링 시큐리티의 동작 구조
스프링 시큐리티는 서블릿 필터를 기반으로 동작하여 Dispatcher Servlet앞에 필터가 배치되어 있습니다.

위의 그림에서 FilterChain은 서블릿 컨테이너에서 관리하는 ApplicationFilterChain을 의미합니다. 클라이언트에서 서버로 요청을 보낸면 서블릿 컨테이너는 URI를 해석하여 필터와 서블릿을 매핑합니다.
하지만 필터는 서블릿 컨테이너에서 관리하고, 생명주기가 서블릿 컨테이너에 의해서 생성되고 등록되기 때문에, Bean을 통해서 필터를 등록하는 것이 불가능하다.
이러한 면을 극복하기 위해서 스프링 시큐리티에서는 사용하고자 하는 필터 체인을 서블릿 컨테이너의 필터 사이에서 동작시키기 위해 아래와 같이 DelegatingFilterProxy를 사용합니다.

DelegatingFilterProxy는 서블릿 컨테이너의 생명주기와 스프링 애플리케이션 컨텍스트 사이에서 Proxy 역할을 수행하는 필터의 구현체입니다. 표준 서블릿 필터를 구현하고 있으며, 역할을 위임할 필터체인 프록시를 내부에 갖고있습니다. 필터체인 프록시는 스프링 부트의 자동 설정(Auto Configuration)에 의해 자동 생성 됩니다.
사용자, 즉 개발자는 FilterChainProxy를 통해서 커스텀한 필터의 구현체를 Bean으로 등록하고 DelegatingFilterProxy 내부에 FilterChainProxy를 통해서 Spring Security에 Bean으로 등록된 필터를 거쳐서 컨트롤러 단으로 넘어가게 됩니다.
스프링 보안 필터 체인에서 사용하는 필터는 여러 종류가 있으며, 각 필터마다 실행되는 순서가 다르다.
공식 문서에서는 다음과 같이 정의했다.
순서 | 필터 이름 | 역할 |
---|---|---|
1 | ChannelProcessingFilter | 채널 보안을 처리 (예: HTTPS 사용 강제) |
2 | WebAsyncManagerIntegrationFilter | 비동기 웹 요청의 보안 컨텍스트 관리 |
3 | SecurityContextPersistenceFilter | SecurityContext의 지속성을 관리 |
4 | HeaderWriterFilter | HTTP 헤더에 보안 관련 헤더 추가 |
5 | CorsFilter | CORS 설정 적용 |
6 | CsrfFilter | CSRF 공격 방지 |
7 | LogoutFilter | 로그아웃 처리 |
8 | OAuth2AuthorizationRequestRedirectFilter | OAuth2 인증 요청 리다이렉션 |
9 | Saml2WebSsoAuthenticationRequestFilter | SAML2 SSO 인증 요청 처리 |
10 | X509AuthenticationFilter | X.509 인증서 기반 인증 처리 |
11 | AbstractPreAuthenticatedProcessingFilter | 사전 인증 정보 처리 |
12 | CasAuthenticationFilter | CAS 인증 처리 |
13 | OAuth2LoginAuthenticationFilter | OAuth2 로그인 인증 처리 |
14 | Saml2WebSsoAuthenticationFilter | SAML2 SSO 인증 처리 |
15 | UsernamePasswordAuthenticationFilter | 사용자 이름/비밀번호 기반 인증 |
16 | OpenIDAuthenticationFilter | OpenID 인증 처리 |
17 | DefaultLoginPageGeneratingFilter | 기본 로그인 페이지 생성 |
18 | DefaultLogoutPageGeneratingFilter | 기본 로그아웃 페이지 생성 |
19 | ConcurrentSessionFilter | 동시 세션 관리 |
20 | DigestAuthenticationFilter | Digest 인증 처리 |
21 | BearerTokenAuthenticationFilter | Bearer 토큰 인증 처리 |
22 | BasicAuthenticationFilter | 기본 HTTP 인증 처리 |
23 | RequestCacheAwareFilter | 요청 캐시 관리 |
24 | SecurityContextHolderAwareRequestFilter | SecurityContext 관련 요청 필터링 |
25 | JaasApiIntegrationFilter | Jaas API 통합 처리 |
26 | RememberMeAuthenticationFilter | Remember-Me 인증 처리 |
27 | AnonymousAuthenticationFilter | 익명 사용자 인증 |
28 | OAuth2AuthorizationCodeGrantFilter | OAuth2 Authorization Code Grant 처리 |
29 | SessionManagementFilter | 세션 관리와 관련된 보안 검사 |
30 | ExceptionTranslationFilter | 보안 예외 처리 |
31 | FilterSecurityInterceptor | URL 접근 제어 및 권한 검사 |
32 | SwitchUserFilter | 사용자 전환 처리 |
보안 필터체인은 WebSecurityConfigurerAdapter 클래스를 상속받아 설정할 수 있습니다.
이전에 봤던 것처럼 필터체인 프록시는 여러 보안 필터체인을 가질 수 있는데, 여러 보안 필터체인을 만들기 위해서는 WebSecurityConfigurerAdapter 클래스를 상속받는 클래스를 여러개 생성하면 됩니다. 여러개인 경우 @Order를 통해 우선순위를 부여하면 됩니다.
13.4 JWT
JWT는 Json Web Token의 약자로 당사자 간에 정보를 JSON 형태로 안전하게 전송하기 위한 토큰입니다. JWT는 URL로 이용할 수 있는 문자열로만 구성돼 있으며, 디지털 서명이 적용돼 있어 신뢰할 수 있습니다. JWT는 주로 서버와의 통신에서 권한 인가를 위해 사용됩니다. URL에서 사용할 수 있는 문자열로만 구성돼 있기 때문에 HTTP 구성 요소 어디든 위치할 수 있습니다.
JWT는 점(".")으로 구분되며 크게 3부분으로 나뉩니다.
맨 앞은 헤더, 중간은 내용, 마지막은 서명에 해당됩니다.

Header
JWT의 헤더는 검증과 관련된 내용을 담고 있습니다. 기본적으로는 해싱알고리즘과 토큰의 타입을 작성합니다.

Payload
JWT의 Payload에는 토큰에 담는 정보를 포함합니다. 이곳에 포함된 속성들은 클레임(Claim)이라고 하며, 크게 3가지로 분류됩니다
1. 등록된 클레임
2. 공개 클레임
3. 비공개 클레임
등록된 클레임은 필수는 아니지만 토큰에 대한 정보를 담기위해 이미 이름이 정해져 있는 클레임을 뜻합니다.


Signature
JWT의 Signature 부분은 인코딩된 헤더, 인코딩된 내용, 비밀키, 헤더의 알고리즘 속성값을 가져와 생성됩니다.
예를 들어, HMAC SHA256 알고리즘을 사용해서 서명을 생성한다면 아래와 같은 내용이 들어있을 것입니다.

아래 사이트에서는 발급받은 JWT 토큰을 디버그할 수 있는 사이트이다.
JWT.IO
JSON Web Tokens are an open, industry standard RFC 7519 method for representing claims securely between two parties.
jwt.io
'책' 카테고리의 다른 글
[Book] 스프링 부트 핵심 가이드 Chap.12 (0) | 2024.08.05 |
---|---|
[Book] 스프링 부트 핵심 가이드 Chap.11 (0) | 2024.08.05 |
[Book] 스프링 부트 핵심 가이드 Chap.10 - 유효성 검사와 예외 처리 (0) | 2024.07.28 |
[Book] 스프링 부트 핵심 가이드 Chap.9 (1) | 2024.07.21 |
[Book] 스프링 부트 핵심 가이드 Chap.8 (0) | 2024.07.14 |

드디어 마지막 장인 13장을 다 읽었다..
Chap.13 서비스의 인증과 권한 부여
서비스를 개발하다보면, 회원간의 별도의 데이터를 저장한다던가, 특정 게시물을 삭제할 때, 요청한 유저가 해당 게시글의 주인인가를 파악하는 로직이 추가되기 마련이다. 이런 경우에 Spring Boot에서는 요청을 보낼때 누가 보냈는지를 넣어서 전달하고 반환받을 수도 있지만, 이런 것은 Spring스럽지 않기 때문에, Spring Boot Security를 사용해서 보안과 인증, 권한을 처리한다.
13.1 보안 용어 이해
인증 Authentication은 사용자가 누구인지 확인하는 단계를 의미한다. 예를 들자면 로그인과 같은 기능이 존재한다.
로그인 Form에 Username과 Password를 입력한 후 전달하고, 서버에서는 해당 데이터가 옳다면 서버에서 인증에 사용하는 방법에 맞는 반환값을 전달한다. JWT와 같은 Token 방식을 채택했을 경우, accessToken을 전달하게 될 것이다.
인가 Authorization은 이전의 인증을 통해 검증된 사용자가 특정 API에 접근할 때, 해당 권한이 있는 지 없는 지를 검사하는 과정을 의미합니다. 예를 들면, 사용자가 특정 게시판에 접근하려고 할때, 해당 유저의 권한을 확인하여 해당 게시판에 접근할 수 있는 지를 확인하고 접근을 허가하거나 거부하는 것이 대표적인 인가의 사례입니다. 인증 단계에서 받은 토큰은 Http Request의 Header 중 Authorization에 넣어서 토큰을 서버로 전달합니다.
접근 주체 principal은 말 그대로 애플리케이션의 기능을 사용하는 주체입니다. 사용자가 될 수도 있고 특정 디바이스에서 호출을 하거나, 시스템에서 사용하게 될 수도 있습니다. 애플리케이션은 앞서 소개한 인증과정을 통해 접근 주체가 신뢰할 수 있는지 확인하고, 인가 과정에서 접근 주체에게 부여된 권한을 확인하는 과정들을 거칩니다.
13.2 Spring Security
스프링 시큐리티는 인증과 인가등의 보안 기능을 제공하는 스프링 하위 프로젝트중 하나로, 보안과 관련된 많은 기능을 제공하기 때문에, 스프링 시큐리티를 활용하면 더욱 편리하게 원하는 기능을 설계할 수 있습니다.
13.3 스프링 시큐리티의 동작 구조
스프링 시큐리티는 서블릿 필터를 기반으로 동작하여 Dispatcher Servlet앞에 필터가 배치되어 있습니다.

위의 그림에서 FilterChain은 서블릿 컨테이너에서 관리하는 ApplicationFilterChain을 의미합니다. 클라이언트에서 서버로 요청을 보낸면 서블릿 컨테이너는 URI를 해석하여 필터와 서블릿을 매핑합니다.
하지만 필터는 서블릿 컨테이너에서 관리하고, 생명주기가 서블릿 컨테이너에 의해서 생성되고 등록되기 때문에, Bean을 통해서 필터를 등록하는 것이 불가능하다.
이러한 면을 극복하기 위해서 스프링 시큐리티에서는 사용하고자 하는 필터 체인을 서블릿 컨테이너의 필터 사이에서 동작시키기 위해 아래와 같이 DelegatingFilterProxy를 사용합니다.

DelegatingFilterProxy는 서블릿 컨테이너의 생명주기와 스프링 애플리케이션 컨텍스트 사이에서 Proxy 역할을 수행하는 필터의 구현체입니다. 표준 서블릿 필터를 구현하고 있으며, 역할을 위임할 필터체인 프록시를 내부에 갖고있습니다. 필터체인 프록시는 스프링 부트의 자동 설정(Auto Configuration)에 의해 자동 생성 됩니다.
사용자, 즉 개발자는 FilterChainProxy를 통해서 커스텀한 필터의 구현체를 Bean으로 등록하고 DelegatingFilterProxy 내부에 FilterChainProxy를 통해서 Spring Security에 Bean으로 등록된 필터를 거쳐서 컨트롤러 단으로 넘어가게 됩니다.
스프링 보안 필터 체인에서 사용하는 필터는 여러 종류가 있으며, 각 필터마다 실행되는 순서가 다르다.
공식 문서에서는 다음과 같이 정의했다.
순서 | 필터 이름 | 역할 |
---|---|---|
1 | ChannelProcessingFilter | 채널 보안을 처리 (예: HTTPS 사용 강제) |
2 | WebAsyncManagerIntegrationFilter | 비동기 웹 요청의 보안 컨텍스트 관리 |
3 | SecurityContextPersistenceFilter | SecurityContext의 지속성을 관리 |
4 | HeaderWriterFilter | HTTP 헤더에 보안 관련 헤더 추가 |
5 | CorsFilter | CORS 설정 적용 |
6 | CsrfFilter | CSRF 공격 방지 |
7 | LogoutFilter | 로그아웃 처리 |
8 | OAuth2AuthorizationRequestRedirectFilter | OAuth2 인증 요청 리다이렉션 |
9 | Saml2WebSsoAuthenticationRequestFilter | SAML2 SSO 인증 요청 처리 |
10 | X509AuthenticationFilter | X.509 인증서 기반 인증 처리 |
11 | AbstractPreAuthenticatedProcessingFilter | 사전 인증 정보 처리 |
12 | CasAuthenticationFilter | CAS 인증 처리 |
13 | OAuth2LoginAuthenticationFilter | OAuth2 로그인 인증 처리 |
14 | Saml2WebSsoAuthenticationFilter | SAML2 SSO 인증 처리 |
15 | UsernamePasswordAuthenticationFilter | 사용자 이름/비밀번호 기반 인증 |
16 | OpenIDAuthenticationFilter | OpenID 인증 처리 |
17 | DefaultLoginPageGeneratingFilter | 기본 로그인 페이지 생성 |
18 | DefaultLogoutPageGeneratingFilter | 기본 로그아웃 페이지 생성 |
19 | ConcurrentSessionFilter | 동시 세션 관리 |
20 | DigestAuthenticationFilter | Digest 인증 처리 |
21 | BearerTokenAuthenticationFilter | Bearer 토큰 인증 처리 |
22 | BasicAuthenticationFilter | 기본 HTTP 인증 처리 |
23 | RequestCacheAwareFilter | 요청 캐시 관리 |
24 | SecurityContextHolderAwareRequestFilter | SecurityContext 관련 요청 필터링 |
25 | JaasApiIntegrationFilter | Jaas API 통합 처리 |
26 | RememberMeAuthenticationFilter | Remember-Me 인증 처리 |
27 | AnonymousAuthenticationFilter | 익명 사용자 인증 |
28 | OAuth2AuthorizationCodeGrantFilter | OAuth2 Authorization Code Grant 처리 |
29 | SessionManagementFilter | 세션 관리와 관련된 보안 검사 |
30 | ExceptionTranslationFilter | 보안 예외 처리 |
31 | FilterSecurityInterceptor | URL 접근 제어 및 권한 검사 |
32 | SwitchUserFilter | 사용자 전환 처리 |
보안 필터체인은 WebSecurityConfigurerAdapter 클래스를 상속받아 설정할 수 있습니다.
이전에 봤던 것처럼 필터체인 프록시는 여러 보안 필터체인을 가질 수 있는데, 여러 보안 필터체인을 만들기 위해서는 WebSecurityConfigurerAdapter 클래스를 상속받는 클래스를 여러개 생성하면 됩니다. 여러개인 경우 @Order를 통해 우선순위를 부여하면 됩니다.
13.4 JWT
JWT는 Json Web Token의 약자로 당사자 간에 정보를 JSON 형태로 안전하게 전송하기 위한 토큰입니다. JWT는 URL로 이용할 수 있는 문자열로만 구성돼 있으며, 디지털 서명이 적용돼 있어 신뢰할 수 있습니다. JWT는 주로 서버와의 통신에서 권한 인가를 위해 사용됩니다. URL에서 사용할 수 있는 문자열로만 구성돼 있기 때문에 HTTP 구성 요소 어디든 위치할 수 있습니다.
JWT는 점(".")으로 구분되며 크게 3부분으로 나뉩니다.
맨 앞은 헤더, 중간은 내용, 마지막은 서명에 해당됩니다.

Header
JWT의 헤더는 검증과 관련된 내용을 담고 있습니다. 기본적으로는 해싱알고리즘과 토큰의 타입을 작성합니다.

Payload
JWT의 Payload에는 토큰에 담는 정보를 포함합니다. 이곳에 포함된 속성들은 클레임(Claim)이라고 하며, 크게 3가지로 분류됩니다
1. 등록된 클레임
2. 공개 클레임
3. 비공개 클레임
등록된 클레임은 필수는 아니지만 토큰에 대한 정보를 담기위해 이미 이름이 정해져 있는 클레임을 뜻합니다.


Signature
JWT의 Signature 부분은 인코딩된 헤더, 인코딩된 내용, 비밀키, 헤더의 알고리즘 속성값을 가져와 생성됩니다.
예를 들어, HMAC SHA256 알고리즘을 사용해서 서명을 생성한다면 아래와 같은 내용이 들어있을 것입니다.

아래 사이트에서는 발급받은 JWT 토큰을 디버그할 수 있는 사이트이다.
JWT.IO
JSON Web Tokens are an open, industry standard RFC 7519 method for representing claims securely between two parties.
jwt.io
'책' 카테고리의 다른 글
[Book] 스프링 부트 핵심 가이드 Chap.12 (0) | 2024.08.05 |
---|---|
[Book] 스프링 부트 핵심 가이드 Chap.11 (0) | 2024.08.05 |
[Book] 스프링 부트 핵심 가이드 Chap.10 - 유효성 검사와 예외 처리 (0) | 2024.07.28 |
[Book] 스프링 부트 핵심 가이드 Chap.9 (1) | 2024.07.21 |
[Book] 스프링 부트 핵심 가이드 Chap.8 (0) | 2024.07.14 |