복붙노트

[SPRING] 스프링 보안 필터 체인 작동 방법

SPRING

스프링 보안 필터 체인 작동 방법

Spring 보안은 요청을 가로 채고 인증 (부재)을 감지하고 인증 진입 점으로 리디렉션하거나 요청을 권한 서비스에 전달하는 필터 체인을 기반으로하며 결국에는 요청이 서블릿에 도달하거나 보안 예외를 throw하도록합니다. (인증되지 않거나 인증되지 않음). DelegatingFitlerProxy는 이러한 필터를 함께 연결합니다. 이러한 작업을 수행하기 위해 UserDetailsService 및 AuthenticationManager와 같은 이러한 필터 액세스 서비스.

체인의 키 필터는 (순서대로)

나는이 필터들이 어떻게 사용되는지 혼란 스럽다. Spring이 form-login을 제공하면 UsernamePasswordAuthenticationFilter는 / login에만 사용되며 후자의 필터는 사용되지 않습니까? form-login 네임 스페이스 요소가 이러한 필터를 자동으로 구성합니까? 모든 요청 (인증 여부)이 비 로그인 URL에 대한 FilterSecurityInterceptor에 도달합니까?

로그인에서 검색되는 JWT-token으로 내 REST API를 보호하려면 어떻게해야합니까? 두 개의 네임 스페이스 구성 http 태그, 권리를 구성해야합니까? 다른 하나는 UsernamePasswordAuthenticationFilter를 사용하여 로그인하고, 다른 하나는 REST URL을 사용자 지정 JwtAuthenticationFilter와 함께 사용합니다.

두 개의 HTTP 요소를 구성하면 springSecurityFitlerChains가 두 개 생성됩니까? form-login을 선언 할 때까지 UsernamePasswordAuthenticationFilter가 기본적으로 해제되어 있습니까? SecurityContextPersistenceFilter를 JSESSIONID가 아닌 기존 JWT 토큰에서 인증을 얻는 것으로 대체하는 방법은 무엇입니까?

해결법

  1. ==============================

    1.Spring 보안 필터 체인은 매우 복잡하고 유연한 엔진입니다.

    Spring 보안 필터 체인은 매우 복잡하고 유연한 엔진입니다.

    현재 stable 릴리스 4.2.1 문서, 13.3 절 필터 순서를 보면 전체 필터 체인의 필터 구성을 볼 수 있습니다.

    자, 저는 여러분의 질문에 하나씩 차례대로 노력할 것입니다 :

    섹션을 구성하고 나면 각 섹션마다 적어도 하나의 인증 메커니즘을 제공해야합니다. 이것은 방금 언급 한 Spring Security 문서의 13.3 Filter Ordering 섹션에서 그룹 4와 일치하는 필터 중 하나 여야합니다.

    다음은 구성 할 수있는 최소 유효한 보안 : http 요소입니다.

    <security:http authentication-manager-ref="mainAuthenticationManager" 
                   entry-point-ref="serviceAccessDeniedHandler">
        <security:intercept-url pattern="/sectest/zone1/**" access="hasRole('ROLE_ADMIN')"/>
    </security:http>
    

    이 필터는 필터 체인 프록시에서 다음과 같이 구성됩니다.

    {
            "1": "org.springframework.security.web.context.SecurityContextPersistenceFilter",
            "2": "org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter",
            "3": "org.springframework.security.web.header.HeaderWriterFilter",
            "4": "org.springframework.security.web.csrf.CsrfFilter",
            "5": "org.springframework.security.web.savedrequest.RequestCacheAwareFilter",
            "6": "org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter",
            "7": "org.springframework.security.web.authentication.AnonymousAuthenticationFilter",
            "8": "org.springframework.security.web.session.SessionManagementFilter",
            "9": "org.springframework.security.web.access.ExceptionTranslationFilter",
            "10": "org.springframework.security.web.access.intercept.FilterSecurityInterceptor"
        }
    

    참고 : 나는 FilterChainProxy를 @Autowires하는 간단한 RestController를 생성하고 그 내용을 반환한다.

        @Autowired
        private FilterChainProxy filterChainProxy;
    
        @Override
        @RequestMapping("/filterChain")
        public @ResponseBody Map<Integer, Map<Integer, String>> getSecurityFilterChainProxy(){
            return this.getSecurityFilterChainProxy();
        }
    
        public Map<Integer, Map<Integer, String>> getSecurityFilterChainProxy(){
            Map<Integer, Map<Integer, String>> filterChains= new HashMap<Integer, Map<Integer, String>>();
            int i = 1;
            for(SecurityFilterChain secfc :  this.filterChainProxy.getFilterChains()){
                //filters.put(i++, secfc.getClass().getName());
                Map<Integer, String> filters = new HashMap<Integer, String>();
                int j = 1;
                for(Filter filter : secfc.getFilters()){
                    filters.put(j++, filter.getClass().getName());
                }
                filterChains.put(i++, filters);
            }
            return filterChains;
        }
    

    여기서는 하나의 최소 구성으로 요소를 선언함으로써 모든 기본 필터가 포함되지만 인증 유형 (13.3 필터 주문 섹션의 네 번째 그룹)이 아닌 것을 볼 수 있습니다. 따라서 실제로 security : http 요소, SecurityContextPersistenceFilter, ExceptionTranslationFilter 및 FilterSecurityInterceptor를 선언하면 자동으로 구성된다는 것을 의미합니다.

    실제로 하나의 인증 처리 메커니즘을 구성해야하며 보안 네임 스페이스 Bean이이를 처리하여 시작시 오류가 발생하지만 에 entry-point-ref 특성을 추가하면 무시할 수 있습니다.

    구성에 기본 을 추가하면 다음과 같이됩니다.

    <security:http authentication-manager-ref="mainAuthenticationManager">
        <security:intercept-url pattern="/sectest/zone1/**" access="hasRole('ROLE_ADMIN')"/>
        <security:form-login />
    </security:http>
    

    이제 filterChain은 다음과 같습니다.

    {
            "1": "org.springframework.security.web.context.SecurityContextPersistenceFilter",
            "2": "org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter",
            "3": "org.springframework.security.web.header.HeaderWriterFilter",
            "4": "org.springframework.security.web.csrf.CsrfFilter",
            "5": "org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter",
            "6": "org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter",
            "7": "org.springframework.security.web.savedrequest.RequestCacheAwareFilter",
            "8": "org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter",
            "9": "org.springframework.security.web.authentication.AnonymousAuthenticationFilter",
            "10": "org.springframework.security.web.session.SessionManagementFilter",
            "11": "org.springframework.security.web.access.ExceptionTranslationFilter",
            "12": "org.springframework.security.web.access.intercept.FilterSecurityInterceptor"
        }
    

    이제이 두 개의 필터 org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter와 org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter가 FilterChainProxy에서 생성되고 설정됩니다.

    그래서, 지금, 질문 :

    예, 요청이 UsernamePasswordAuthenticationFilter URL과 일치하는 경우 로그인 처리 메커니즘을 완료하려고 시도하는 데 사용됩니다. 이 URL은 모든 요청과 일치하도록 구성하거나 변경 될 수 있습니다.

    동일한 FilterchainProxy (예 : HttpBasic, CAS 등)에 둘 이상의 인증 처리 메커니즘이 구성되어있을 수도 있습니다.

    아니요, form-login 요소는 UsernamePasswordAUthenticationFilter를 구성하고 로그인 페이지 URL을 제공하지 않을 경우 간단한 자동 생성 로그인으로 끝나는 org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter도 구성합니다 페이지.

    다른 필터는 기본적으로 security : "none"속성이없는 요소를 생성하여 자동으로 구성됩니다.

    모든 요청은 요청에 도달해야합니다. 요청이 요청 된 URL에 도달 할 권한이 있는지 여부를 처리하는 요소이기 때문입니다. 그러나 전에 처리 된 일부 필터는 FilterChain.doFilter (request, response);를 호출하지 않고 필터 체인 처리를 중지시킬 수 있습니다. 예를 들어 CSRF 필터는 요청에 csrf 매개 변수가없는 경우 필터 체인 처리를 중지 할 수 있습니다.

    아니, 당신은 이런 식으로 강요 당하지 않습니다. 동일한 http 요소에서 UsernamePasswordAuthenticationFilter와 JwtAuthenticationFilter를 모두 선언 할 수 있지만이 필터의 구체적인 동작에 따라 달라집니다. 두 접근법 모두 가능하며 finnally 선택할 수있는 방법은 자신의 취향에 달려 있습니다.

    예, 맞습니다.

    예, 게시 된 configs 각각에서 제기 된 필터에서 볼 수 있습니다.

    에 세션 전략을 구성하기 만하면 SecurityContextPersistenceFilter를 피할 수 있습니다. 다음과 같이 구성하면됩니다.

    <보안 : http create-session = "stateless">

    또는이 경우 요소 안에 다른 필터를 겹쳐 쓸 수 있습니다.

    <security:http ...>  
       <security:custom-filter ref="myCustomFilter" position="SECURITY_CONTEXT_FILTER"/>    
    </security:http>
    <beans:bean id="myCustomFilter" class="com.xyz.myFilter" />
    

    편집하다:

    결국 각 필터 자체의 구현에 따라 달라 지지만 후자의 인증 필터가 선행 필터에 의해 결국 생성 된 이전 인증을 덮어 쓸 수 있다는 것은 사실입니다.

    그러나 이것이 반드시 일어나는 것은 아닙니다. 나는 Http 헤더 또는 요청 본문 둘 다로 제공 될 수있는 일종의 승인 토큰을 사용하는 보안 REST 서비스에 몇 가지 제작 사례를 갖고있다. 그래서 저는 토큰을 복구하는 두 개의 필터를 구성합니다. 하나의 경우에는 Http Header에서, 다른 하나는 자체 나머지 요청의 요청 본문에서 구성합니다. 하나의 HTTP 요청이 HTTP 헤더와 요청 본문 둘 다에 해당 인증 토큰을 제공하면 두 필터가 모두 인증 메커니즘을 실행하여 관리자에게 위임하려고 시도하지만 실제로 요청이 있는지 여부를 확인하는 것만으로 쉽게 피할 수 있다는 사실은 사실입니다. 각 필터의 ​​doFilter () 메소드의 시작 부분에서 이미 인증되었습니다.

    복수의 인증 필터를 가지는 것은, 복수의 인증 프로 바이더를 가지는 것에 관련 합니다만, 강제하지 않습니다. 전에 노출 된 경우에는 두 개의 인증 필터가 있지만 두 필터 모두 동일한 유형의 인증 객체를 생성하므로 하나의 인증 공급자 만 있으므로 두 경우 모두 인증 관리자가 동일한 공급자에게 위임합니다.

    그리고 이와 반대로, 나는 하나의 UsernamePasswordAuthenticationFilter를 게시하지만 사용자 자격 증명은 모두 DB 또는 LDAP에 포함될 수 있으므로 두 개의 UsernamePasswordAuthenticationToken 지원 제공자가 있으며 AuthenticationManager는 필터에서 공급자로의 인증 시도를 위임합니다. 자격 증명의 유효성을 검사합니다.

    따라서 인증 필터의 양이 인증 공급자의 양을 결정하거나 제공자 양이 필터의 양을 결정하지 않는다는 것이 확실합니다.

    이전에이 필터를주의 깊게 살펴 보진 않았지만, 마지막 질문을 한 후에 구현을 확인했습니다. 일반적으로 봄에 거의 모든 것이 구성되거나 확장되거나 지나치게 커질 수있었습니다.

    SecurityContextPersistenceFilter는 SecurityContextRepository 구현에서 SecurityContext에 대한 검색을 위임합니다. 기본적으로 HttpSessionSecurityContextRepository가 사용되지만 필터의 생성자 중 하나를 사용하여 변경할 수 있습니다. 따라서 여러분의 필요에 맞는 SecurityContextRepository를 작성하고 SecurityContextPersistenceFilter에서 구성하는 것이 더 좋을 수도 있습니다. SecurityContextPersistenceFilter에서 모든 것을 처음부터 만들기보다는 검증 된 동작을 신뢰하는 것입니다.

  2. ==============================

    2.아니요, UsernamePasswordAuthenticationFilter는 AbstractAuthenticationProcessingFilter를 확장하며 RequestMatcher를 포함합니다. 즉, 사용자가 처리 URL을 정의 할 수 있음을 의미합니다.이 필터는 RequestMatcher 만 처리하고 요청 URL과 일치합니다. 기본 처리 URL은 / login입니다.

    아니요, UsernamePasswordAuthenticationFilter는 AbstractAuthenticationProcessingFilter를 확장하며 RequestMatcher를 포함합니다. 즉, 사용자가 처리 URL을 정의 할 수 있음을 의미합니다.이 필터는 RequestMatcher 만 처리하고 요청 URL과 일치합니다. 기본 처리 URL은 / login입니다.

    UsernamePasswordAuthenticationFilter가 chain.doFilter (request, response);를 실행하면 나중에 필터가 요청을 처리 할 수 ​​있습니다.

    코어 필터에 대한 자세한 내용

    UsernamePasswordAuthenticationFilter는 에 의해 생성되며 표준 필터 별칭 및 주문입니다.

    그것은 전에 fitler가 성공했는지에 따라 다르지만, FilterSecurityInterceptor가 마지막 fitler입니다.

    예, 모든 fitlerChain에는 RequestMatcher가 있습니다. RequestMatcher가 요청과 일치하면 요청은 fitler 체인의 fitler에 의해 처리됩니다.

    기본 RequestMatcher는 패턴을 구성하지 않거나 특정 URL (

    필터에 대해 더 알고 싶다면 스프링 보안에서 소스 코드를 확인할 수 있다고 생각합니다. doFilter (ServletRequest 요청, ServletResponse 응답, FilterChain filterChain)

  3. from https://stackoverflow.com/questions/41480102/how-spring-security-filter-chain-works by cc-by-sa and MIT license