1. 概要

Spring Security Java構成サポートは、アプリケーションのセキュリティマッピングとルールを定義するための強力で流暢なAPIを提供します。

この簡単な記事では、この一歩を踏み出し、実際にカスタムコンフィギュレーターを定義する方法を説明します。 これは、カスタムロジックを標準のセキュリティ構成に導入するための高度で柔軟な方法です。

ここでの簡単な例では、エラーステータスコードの特定のリストに応じて、認証されたユーザーのエラーをログに記録する機能を追加します。

2. カスタムSecurityConfigurer

コンフィギュレーターの定義を開始するには、最初にAbstractHttpConfigurerクラスを拡張する必要があります。

public class ClientErrorLoggingConfigurer 
  extends AbstractHttpConfigurer<ClientErrorLoggingConfigurer, HttpSecurity> {

    private List<HttpStatus> errorCodes;
    
    // standard constructors
    
    @Override
    public void init(HttpSecurity http) throws Exception {
        // initialization code
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
       http.addFilterAfter(
         new ClientErrorLoggingFilter(errorCodes), 
         FilterSecurityInterceptor.class);
    }
}

ここで、オーバーライドする必要がある主なメソッドはconfigure()メソッドです。これには、このコンフィギュレーターが適用されるセキュリティ構成が含まれています。

この例では、最後のSpringセキュリティフィルターの後に新しいフィルターを登録しました。 また、応答ステータスのエラーコードをログに記録することを目的としているため、ログに記録するエラーコードを制御するために使用できる errorCodesListプロパティを追加しました。

オプションで、 init()メソッドに構成を追加することもできます。これは、 configure()メソッドの前に実行されます。

次に、カスタム実装に登録するSpringセキュリティフィルタークラスを定義しましょう。

public class ClientErrorLoggingFilter extends GenericFilterBean {

    private static final Logger logger = LogManager.getLogger(
      ClientErrorLoggingFilter.class);
    private List<HttpStatus> errorCodes;

    // standard constructor

    @Override
    public void doFilter(
      ServletRequest request, 
      ServletResponse response, 
      FilterChain chain) 
      throws IOException, ServletException {
        //...

        chain.doFilter(request, response);
    }
}

これは、 GenericFilterBean を拡張し、 doFilter()メソッドをオーバーライドする標準のSpringフィルタークラスです。 メッセージの表示に使用するロガーとerrorCodesのListを表す2つのプロパティがあります。

doFilter()メソッドを詳しく見てみましょう。

Authentication auth = SecurityContextHolder.getContext().getAuthentication();
if (auth == null) {
    chain.doFilter(request, response);
    return;
}
int status = ((HttpServletResponse) response).getStatus();
if (status < 400 || status >= 500) {
    chain.doFilter(request, response);
    return;
}
if (errorCodes == null) {
    logger.debug("User " + auth.getName() + " encountered error " + status);
} else {
    if (errorCodes.stream().anyMatch(s -> s.value() == status)) {
        logger.debug("User " + auth.getName() + " encountered error " + status);
    }
}

ステータスコードがクライアントエラーステータスコード、つまり400〜500の場合、errorCodesリストを確認します。

これが空の場合、クライアントエラーステータスコードが表示されます。 それ以外の場合は、最初にエラーコードがステータスコードの指定されたリストの一部であるかどうかを確認します。

3. カスタムコンフィギュレータの使用

カスタムAPIができたので、 Beanを定義し、 HttpSecurity:のapply()メソッドを使用して、SpringSecurity構成に追加できます。

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
          //...
          .and()
          .apply(clientErrorLogging());
    }

    @Bean
    public ClientErrorLoggingConfigurer clientErrorLogging() {
        return new ClientErrorLoggingConfigurer() ;
    }
}

ログに記録するエラーコードの特定のリストを使用してBeanを定義することもできます。

@Bean
public ClientErrorLoggingConfigurer clientErrorLogging() {
    return new ClientErrorLoggingConfigurer(Arrays.asList(HttpStatus.NOT_FOUND)) ;
}

そしてそれがすべてです! これで、セキュリティ構成にカスタムフィルタが含まれ、ログメッセージが表示されます。

カスタムコンフィギュレータをデフォルトで追加する場合は、 META-INF /spring.factoriesファイルを使用できます。

org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer = com.baeldung.dsl.ClientErrorLoggingConfigurer

手動で無効にするには、 disable()メソッドを使用できます。

//...
.apply(clientErrorLogging()).disable();

4. 結論

このクイックチュートリアルでは、Springセキュリティ構成サポートの高度な機能に焦点を当てました–独自のカスタムSecurityConfigurerを定義する方法を見てきました。

いつものように、例の完全なソースコードは、GitHubにあります。