はじめに
この組み合わせで問題が起きて解決したメモです。
Terasolunaの二重送信防止ページについては以下をご覧ください
環境
Adopt Open JDK Hotspot 11.0.3
Spring boot 2.1.0M4
pom.xml
二重送信防止機能についてはTerasolunaの機能を使いますので、Dependencyに追加します。
terasoluna-gfw-common
はいらない気もしますが、なんとなく入っています。
<dependency>
<groupId>org.terasoluna.gfw</groupId>
<artifactId>terasoluna-gfw-common</artifactId>
<version>5.5.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.terasoluna.gfw</groupId>
<artifactId>terasoluna-gfw-web</artifactId>
<version>5.5.1.RELEASE</version>
</dependency>
InterceptorとRequestDataValueProcessorの設定
Terasolunaの二重送信防止機能はInterceptorでRequestにAttributeを設定して、それをキーにRequestDataValueProcessorでhiddenを作りだすみたいな動きをします。
そのため、Interceptorの設定とhiddenを作ってくれるRequestDataValueProcessorの設定を行います。
ここで注意点があり、Spring Securityを使用するとcsrf対策のためのhiddenを埋め込む設定であるCsrfRequestDataValueProcessorが自動的にBean登録されます。
このProcessorは全体で1つしか登録出来ないため、特に何もしなければcsrf対策か二重送信防止かどちらかしか使うことが出来ません。
そこで、Terasoluna内にあるCompositeRequestDataValueProcessor
という複数のRequestDataValueProcessorを使用するためのクラスをBean登録することで両立させることになります。
また、今回は例なので、HandlerInterceptorを全てのURLに設定していますが、必要に応じてexcludePathPatterns
で除外条件を作ってあげてください。
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.web.servlet.support.csrf.CsrfRequestDataValueProcessor;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.support.RequestDataValueProcessor;
import org.terasoluna.gfw.web.mvc.support.CompositeRequestDataValueProcessor;
import org.terasoluna.gfw.web.token.transaction.TransactionTokenInterceptor;
import org.terasoluna.gfw.web.token.transaction.TransactionTokenRequestDataValueProcessor;
@Configuration
public class WebMcvConfig implements WebMvcConfigurer {
@Bean
public TransactionTokenInterceptor transactionTokenInterceptor() {
return new TransactionTokenInterceptor();
}
@Bean
public RequestDataValueProcessor requestDataValueProcessor() {
return new CompositeRequestDataValueProcessor(new CsrfRequestDataValueProcessor(), new TransactionTokenRequestDataValueProcessor());
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(transactionTokenInterceptor()).addPathPatterns("/**");
}
}
Beanの上書きを許容する
Beanはデフォルトだと上書き出来ないように設定されているため、設定で上書き出来るように許容してあげます。
この設定を行わないとBean重複してるとしてエラーとなってしまいます。
ただし、この設定を入れると上書き出来てしまうため、Bean関連の設定がしっかりしていないと思わぬ挙動が発生してしまいます。ご注意ください。
spring:
main:
allow-bean-definition-overriding: true
おわりに
なんでSpringに二重送信防止機能がデフォルトで入っていないのでしょうか。