1. 概要

DelegatingFilterProxy は、SpringアプリケーションコンテキストにアクセスできるFilterクラスに制御を渡すことができるサーブレットフィルターです。 Spring Securityは、この手法に大きく依存しています。

このチュートリアルでは、それについて詳しく説明します。

2.  DelegatingFilterProxy

DelegatingFilterProxy のJavadocには、

標準のサーブレットフィルタのプロキシ。フィルタインターフェイスを実装するSpring管理のBeanに委任します。

サーブレットフィルタを使用する場合は、Java-configまたはweb.xmlfilter-classとして宣言する必要があります。そうしないと、サーブレットコンテナはそれらを無視します。 SpringのDelegatingFilterProxyは、web.xmlとアプリケーションコンテキストの間のリンクを提供します。

2.1. DelegatingFilterProxyの内部動作

DelegatingFilterProxyが制御をSpringbeanに転送する方法を見てみましょう。

初期化中に、DelegatingFilterProxyfilter-nameをフェッチし、SpringApplicationContextからその名前のBeanを取得します。 このBeanは、タイプ javax.Servlet.Filter、ieである必要があります。 「通常の」サーブレットフィルタ。 着信リクエストは、このフィルターBeanに渡されます。

つまり、DelegatingFilterProxyの doFilter()メソッドは、すべての呼び出しをSpring beanに委任し、フィルターbean内のすべてのSpring機能を使用できるようにします。

Javaベースの構成を使用している場合、ApplicationInitializerでのフィルター登録は次のように定義されます。

@Override
protected javax.servlet.Filter[] getServletFilters() {
    DelegatingFilterProxy delegateFilterProxy = new DelegatingFilterProxy();
    delegateFilterProxy.setTargetBeanName("applicationFilter");
    return new Filter[]{delegateFilterProxy};
}

XMLを使用する場合、web.xmlファイルで次のようになります。

<filter>
    <filter-name>applicationFilter</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>

これは、applicationFilterという名前のSpringBeanとして定義されたフィルターを通過するように任意の要求を行うことができることを意味します。

2.2. DelegatingFilterProxyの必要性

DelegatingFilterProxy は、SpringのWebモジュールのクラスです。 実際の宛先に到達する前に、HTTP呼び出しがフィルターを通過するようにするための機能を提供します。 DelegatingFilterProxyを使用すると、 javax.Servlet.Filterインターフェースを実装するクラスをフィルターチェーンに接続できます。

例として、SpringSecurityはDelegatingFilterProxy を使用して、セキュリティフィルターのSpringの依存性注入機能とライフサイクルインターフェイスを利用できるようにします。

DelegatingFilterProxy は、Springのアプリケーションコンテキストまたは web.xml。で構成を提供することにより、リクエストURIパスに従って特定または複数のフィルターを呼び出すことも活用します。

3. カスタムフィルターの作成

上記のように、 DelegatingFilterProxy は、Filterインターフェースを実装する特定のSpringマネージドBeanに委任するサーブレットフィルター自体です。

次のいくつかのセクションでは、カスタムフィルターを作成し、JavaおよびXMLベースの構成を使用して構成します。

3.1. フィルタクラス

リクエストが先に進む前に、リクエスト情報をログに記録する単純なフィルターを作成します。

まず、カスタムフィルタークラスを作成しましょう。

@Component("loggingFilter")
public class CustomFilter implements Filter {

    private static Logger LOGGER = LoggerFactory.getLogger(CustomFilter.class);

    @Override
    public void init(FilterConfig config) throws ServletException {
        // initialize something
    }

    @Override
    public void doFilter(
      ServletRequest request, ServletResponse response, 
      FilterChain chain) throws IOException, ServletException {
 
        HttpServletRequest req = (HttpServletRequest) request;
        LOGGER.info("Request Info : " + req);
        chain.doFilter(request, response);
    }

    @Override
    public void destroy() {
        // cleanup code, if necessary
    }
}

CustomFilterjavax.Servlet.Filterを実装します。 このクラスには、アプリケーションコンテキストでSpringBeanとして登録するための@Componentアノテーションがあります。 このようにして、 DelegatingFilterProxy クラスは、フィルターチェーンの初期化中にフィルタークラスを見つけることができます。

Spring Beanの名前は、 DelegatingFilterProxy [のため、ApplicationInitializerクラスまたは後でweb.xmlにカスタムフィルターを登録するときに指定されたfilter-nameの値と同じである必要があることに注意してください。 X239X]クラスは、アプリケーションコンテキストでまったく同じ名前のフィルターBeanを検索します。

この名前のbeanが見つからない場合は、アプリケーションの起動時に例外が発生します。

3.2. Java構成によるフィルターの構成

Java構成を使用してカスタムフィルターを登録するには、 AbstractAnnotationConfigDispatcherServletInitializergetServletFilters()メソッドをオーバーライドする必要があります。

public class ApplicationInitializer 
  extends AbstractAnnotationConfigDispatcherServletInitializer {
    // some other methods here
 
    @Override
    protected javax.servlet.Filter[] getServletFilters() {
        DelegatingFilterProxy delegateFilterProxy = new DelegatingFilterProxy();
        delegateFilterProxy.setTargetBeanName("loggingFilter");
        return new Filter[]{delegateFilterProxy};
    }
}

3.3. web.xmlを介したフィルターの構成 

web.xmlのフィルター構成がどのように見えるかを見てみましょう。

<filter>
    <filter-name>loggingFilter</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
    <filter-name>loggingFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

filter-class 引数は、タイプ DelegatingFilterProxy であり、作成したフィルタークラスではありません。 このコードを実行して任意のURLをヒットすると、 CustomFilter doFilter()メソッドが実行され、リクエスト情報の詳細がログファイルに表示されます。

4. 結論

この記事では、DelegatingFilterProxyの動作とその使用方法について説明しました。

Spring Securityは、 DelegatingFilterProxy を多用して、不正アクセスからWebAPI呼び出しとリソースを保護します。

ソースコードは、GitHubから入手できます。