Spring Security | Spring Securityとは | web.xmlなしで使用する

アプリケーションサーバーがServlet 3.0以降に対応している場合、web.xmlなしでSpring Securityを使用できます。

.
├── build.gradle
└── src
    └── main
        ├── java
        │   └── sample
        │       └── spring
        │           └── security
        │               ├── MySpringSecurityConfig.java
        │               └── MySpringSecurityInitializer.java
        └── webapp
            └── index.jsp

src/main/java/sample/spring/security/MySpringSecurityInitializer.java

package sample.spring.security;

import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;

public class MySpringSecurityInitializer extends AbstractSecurityWebApplicationInitializer {
    public MySpringSecurityInitializer() {
        super(MySpringSecurityConfig.class);
    }
}

MySpringSecurityConfig.javaindex.jspは変更がないため省略します。

web.xmlを削除し、MySpringSecurityInitializerを追加します。このクラスはAbstractSecurityWebApplicationInitializerを継承し、親コンストラクターへJava設定クラスを渡します。これにより、以前のweb.xml設定は不要になります。

構造

この機能はServlet 3.0で追加されたAPIを使用します。

ServletContainerInitializer

AbstractSecurityWebApplicationInitializerWebApplicationInitializerを実装します。Javadocには、実装がSpringServletContainerInitializerによって自動検出され、Servlet 3.0コンテナによって自動的に起動されると説明されています。

WebApplicationInitializer.java

/**
 * ...
 *
 * <p>Implementations of this SPI will be detected automatically by {@link
 * SpringServletContainerInitializer}, which itself is bootstrapped automatically
 * by any Servlet 3.0 container. See {@linkplain SpringServletContainerInitializer its
 * Javadoc} for details on this bootstrapping mechanism.
 * ...
 */
public interface WebApplicationInitializer {

SpringServletContainerInitializerServletContainerInitializerを実装し、@HandlesTypesが付与されています。

@HandlesTypes(WebApplicationInitializer.class)
public class SpringServletContainerInitializer implements ServletContainerInitializer {
   ...

サーブレットコンテナの起動時にonStartup(Set<Class<?>>, ServletContext)が実行されます。コンテナは@HandlesTypesで指定された型に関連するクラスを検出し、第1引数へ渡します。SpringServletContainerInitializerWebApplicationInitializerの実装を受け取り、インスタンスを作成してonStartup(ServletContext)を実行します。

AbstractSecurityWebApplicationInitializer

AbstractSecurityWebApplicationInitializer.onStartup(ServletContext)は、以前web.xmlで定義していた設定を実行します。

public abstract class AbstractSecurityWebApplicationInitializer
        implements WebApplicationInitializer {

    public static final String DEFAULT_FILTER_NAME = "springSecurityFilterChain";

    public final void onStartup(ServletContext servletContext) throws ServletException {
        beforeSpringSecurityFilterChain(servletContext);
        if (this.configurationClasses != null) {
            AnnotationConfigWebApplicationContext rootAppContext = new AnnotationConfigWebApplicationContext();
            rootAppContext.register(this.configurationClasses);
            servletContext.addListener(new ContextLoaderListener(rootAppContext));
        }
        if (enableHttpSessionEventPublisher()) {
            servletContext.addListener(
                    "org.springframework.security.web.session.HttpSessionEventPublisher");
        }
        servletContext.setSessionTrackingModes(getSessionTrackingModes());
        insertSpringSecurityFilterChain(servletContext);
        afterSpringSecurityFilterChain(servletContext);
    }

    private void insertSpringSecurityFilterChain(ServletContext servletContext) {
        String filterName = DEFAULT_FILTER_NAME;
        DelegatingFilterProxy springSecurityFilterChain = new DelegatingFilterProxy(filterName);
        String contextAttribute = getWebApplicationContextAttribute();
        if (contextAttribute != null) {
            springSecurityFilterChain.setContextAttribute(contextAttribute);
        }
        registerFilter(servletContext, true, filterName, springSecurityFilterChain);
    }
}

要点は、以前web.xmlに記述していた設定を実装側で行うことです。