2017-05-28 29 views
0

私は、スプリングセキュリティが有効になっている既存のSpring WebMVCアプリケーションを持っています。今、私はSpring SecurityのCSRFチェックを有効にしたいと思います。Spring Security CSRFトレーニングモード

しかし、トレーニングモードで動作させたいと思っています。したがって、CSRF-Filterは、欠落しているCSRFトークンだけをログに記録して、時折実装できるようにする必要があります。

CSRF処理のためのSpring-Securityにこのようなトレーニングモードはありますか?

私は、カスタムorg.springframework.security.web.access.AccessDeniedHandlerを実装し、WebSecurityConfigurerAdapterでそれを設定しようとしました:

http.exceptionHandling().accessDeniedHandler(new MyCustomAccessDeniedHandler()); 

しかし、フィルタ・チェーンが停止するので、残念ながらリクエストはsuceedしません。

カスタムCsrfFilterを実装する必要があると思いますが、どうすれば設定できますか?

トレーニングモードを実装する簡単な方法はありますか? 正しい方向の提案や指針はありますか?

答えて

1

CsrfFilterfinalであるため、オーバーライドまたはラッピングすることは不可能です。

ただし、いくつかの種類のトレーニングモードを達成するためのいくつかのオプションがあります - すべてには特定の欠点とセキュリティ上の問題があります。だからそれには注意してください。

ここに1つの可能なソリューションです:ハンドル/ログインカスタム例外に右CsrfFilter前に、カスタムフィルタを使用したカスタム例外

  • を投げることによって、不足している/無効のトークンを処理するカスタムCsrfFilter#accessDeniedHandlerAccessDeniedHandlerを提供

    1. は、チェーン

    を継続することはここでは次のようになります:

    class MissingCsrfTokenException extends RuntimeException { 
    } 
    
    /** 
    * Post process the CsrfFilter to use a custom AccessDeniedHandler 
    */ 
    @Component 
    class CsrfFilterBeanPostProcessor implements BeanPostProcessor { 
    
        @Override 
        public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { 
         if (bean instanceof CsrfFilter) { 
          CsrfFilter csrfFilter = (CsrfFilter) bean; 
          csrfFilter.setAccessDeniedHandler(new AccessDeniedHandler() { 
    
           /** 
           * Default CsrfFilter AccessDeniedHandler implementation (org.springframework.security.web.access.AccessDeniedHandler) 
           */ 
           AccessDeniedHandler delegate = new AccessDeniedHandlerImpl(); 
    
           @Override 
           public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException { 
    
            // test whether the request requires a valid CsrfToken (or is in training mode) 
            boolean inTrainingMode = ... 
            if (inTrainingMode) { 
             throw new MissingCsrfTokenException(); 
            } else { 
             // delegate to the default AccessDeniedHandler 
             delegate.handle(request, response, accessDeniedException); 
            } 
           } 
          }); 
         } 
         return bean; 
        } 
    
        @Override 
        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { 
         return bean; 
        } 
    } 
    
    /** 
    * Custom Filter that logs the token-exceptions and continues the chain. 
    */ 
    class PreCsrfFilterFilter extends OncePerRequestFilter { 
    
        private Logger logger = LoggerFactory.getLogger(PreCsrfFilterFilter.class); 
    
        @Override 
        protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { 
         try { 
          filterChain.doFilter(request, response); 
         } catch (MissingCsrfTokenException ex) { 
          // log and continue the filter chain 
          logger.warn("No CSRF-Token found for {}", request.getRequestURI()); 
          filterChain.doFilter(request, response); 
         } 
        } 
    } 
    
    @Configuration 
    @EnableWebSecurity 
    class Config extends WebSecurityConfigurerAdapter { 
    
        @Override 
        protected void configure(HttpSecurity http) throws Exception { 
         http 
           .authorizeRequests() 
           .anyRequest().authenticated() 
           .and() 
           .formLogin().and() 
           .httpBasic() 
           .and() 
           // add the custom filter before the CsrfFilter 
           .addFilterBefore(new PreCsrfFilterFilter(), CsrfFilter.class); 
        } 
    } 
    
  • +0

    ありがとうございました!このソリューションは私のために働く。私は特に、フィルタチェーン内で例外をキャッチして "トリック"が好きです。私に 'BeanPostProcessor'を指摘してくれてありがとう。私はこれを知らなかった。私の考えでは、これは 'CsrfFilter'の' AccessDeniedHandler'だけを変更する方が、私がやろうとしていたようにグローバルに行うよりもクリーンです。 – Tarator

    +0

    フィードバックありがとう!お役に立てて嬉しいです! – fateddy

    関連する問題