カスタムSpring SecurityConfigurer

カスタムSpring SecurityConfigurer

1. 概要

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

この簡単な記事では、これを一歩進めて、実際にカスタムコンフィギュレーターを定義する方法を説明します。 this is an advanced and flexible way to introduce custom logic into a standard security configuration.

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

2. カスタムSecurityConfigurer

コンフィギュレーターの定義を開始するには、最初にwe need to extend the AbstractHttpConfigurer classを実行します。

public class ClientErrorLoggingConfigurer
  extends AbstractHttpConfigurer {

    private List 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);
    }
}

ここで、the main method we need to override is the configure() method –このコンフィギュレーターが適用されるセキュリティ構成が含まれています。

この例では、最後のSpringSecurityフィルターの後に新しいフィルターを登録しました。 また、応答ステータスのエラーコードをログに記録する予定なので、ログに記録するエラーコードを制御するために使用できるerrorCodes Listプロパティを追加しました。

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

次に、カスタム実装に登録するSpringSecurityフィルタークラスを定義しましょう。

public class ClientErrorLoggingFilter extends GenericFilterBean {

    private static final Logger logger = LogManager.getLogger(
      ClientErrorLoggingFilter.class);
    private List 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リストを確認します。

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

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

これでカスタムAPIができたので、HttpSecurity:we can add it to the Spring Security configuration by defining the bean, then by using the apply() method

@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.example.dsl.ClientErrorLoggingConfigurer

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

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

4. 結論

このクイックチュートリアルでは、Spring Security構成サポートの高度な機能であるwe’ve seen how to define our own, custom SecurityConfigurerに焦点を当てました。

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