이전글:

2023.12.10 - [웹/Spring] - Spring Security 구조에 대해서 - Printing the Security Filters

 

Spring Security 구조에 대해서 - Printing the Security Filters

이전글: 2023.12.09 - [웹/Spring] - Spring Security 구조에 대해서 -Security Filters Spring Security 구조에 대해서 -Security Filters 2023.12.09 - [웹/Spring] - Spring Security 구조에 대해서 - SecurityFilterChain Spring Security 구조

kwaksh2319.tistory.com

 

이전엔 securityFilter Print해주는걸 확인했는데요. 이번엔 filterChain에 CustomFilter를 추가하는것에 대해서 작성해보려합니다.

아래 코드를 보시면 

import java.io.IOException;

import jakarta.servlet.Filter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import org.springframework.security.access.AccessDeniedException;

public class TenantFilter implements Filter {

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;

        String tenantId = request.getHeader("X-Tenant-Id"); (1)
        boolean hasAccess = isUserAllowed(tenantId); (2)
        if (hasAccess) {
            filterChain.doFilter(request, response); (3)
            return;
        }
        throw new AccessDeniedException("Access denied"); (4)
    }

}

이코드는 예시 보안필터 코드입니다.

(1) 요청 헤더에서 tenant id를 가져옵니다.

(2) 현재 사용자가 해당 tenant id에 접근할수 잇는지 확인합니다.

(3) 사용자에게 접근 권한이 있다면, 필터체인의 나머지 필터들을 호출합니다.

(4) 사용자에게 접근 권한이 없다면 AccessDeniedException을 발생시킵니다.

 

그렇다면 이 TenantFilter 필터 코드를 security Filter chain을 추가 할겁니다.

@Bean
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http
        // ...
        //TenantFilter 코드 추가 
        .addFilterBefore(new TenantFilter(), AuthorizationFilter.class);(1)
    return http.build();
}

(1) HttpSecurity .addFilterBefore를 사용하여 AuthorizationFilter 이전에 TenantFilter를 추가합니다.

  •    이방식으로 TenantFilter가 인증 필터들 이후에 호출되도록 확실하게 합니다.
  •   또한, HttpSecurity .addFilterAfter를 사용하여 특정 필터 이후에 필터를 추가하거나 , HttpSecurity addFilterAt를 사용하여    필터 체인의 특정 위치에 필터터를 추가할수 있습니다.

'TenantFilter'가 필터 체인에서 호출되어 현재 사용자가 TenentID에 접근할수 있는지를 확인합니다.

 

Spring bean으로 필터를 선언할 때 주의해야 할점이 있습니다. 필터를 @Component로 주석처리하거나 구성에서 Bean으로 선언하면, Spring Boot가 내장 컨테이너에 자동으로 등록합니다.

이것은 필터가 컨테이너와 Spring Security에 의해 각각 한번씩, 그리고 다른순서로 두번홀출될수 있을 의미합니다.

ex)

의존성 주입의 장점을 활용하며넛 중복 호출을 피하려면  Spring boot에서 켄터이너에 필터를 등록하지 말라고 지시할수 있습니다.

이를 위해 FilterRegistrationBean  을 bean을 선언하고 enabled 속성을 false로 설정합니다.

@Bean
public FilterRegistrationBean<TenantFilter> tenantFilterRegistration(TenantFilter filter) {
    FilterRegistrationBean<TenantFilter> registration = new FilterRegistrationBean<>(filter);
    registration.setEnabled(false);
    return registration;
}

참조:

https://docs.spring.io/spring-security/reference/servlet/architecture.html#servlet-print-filters

 

Architecture :: Spring Security

The Security Filters are inserted into the FilterChainProxy with the SecurityFilterChain API. Those filters can be used for a number of different purposes, like authentication, authorization, exploit protection, and more. The filters are executed in a spec

docs.spring.io

 

+ Recent posts