Migration Guide 5.11.0_ja - terasolunaorg/terasoluna-gfw GitHub Wiki
- 1. 5.11.0での主な変更点
-
2. 5.10.0から5.11.0への移行手順
- 2.1. 依存ライブラリを更新
- 2.2. 共通ライブラリが管理するMavenプラグインの最新化
- 2.3. JDBCドライバーのバージョンの変更
- 2.4. RequestMatcherのパス解析方法の変更
- 2.5. JUnit4からJUnit6への移行
- 2.6. JCL1.2からJCL1.3への移行
- 2.7. 画面認可処理に必要なAPIの別モジュールへの切り出し
- 2.8. 認証パスへのForward時に認証処理が動作しない場合について
- 2.9. 制御文字の出力抑止に対応したログフォーマットへの修正
- 2.10. DataSourceの設定方法を変更
- 2.11. Tomcatのパラメータ変更
- 2.12. RestTemplateからRestClientへの移行
- 2.13. Apache HttpComponents HttpClientのSSL(TLS)ハンドシェイクタイムアウトの設定方法の変更
- 2.14. RestTemplateに設定するHttpRequestFactoryの推奨設定の変更
- 2.15. Jackson2からJackson3への移行
- 2.16. Trailing SlashおよびSuffix Pattern Matchingの削除
- 2.17. HttpHeadersのAPI変更
- 2.18. ResponseErrorHandler#handleError(ClientHttpResponse) の削除
- 2.19. @Configurationクラス内でのBean名の重複を許容しない
- 2.20. DaoAuthenticationProviderのデフォルトコンストラクタが削除された
- 2.21. HibernateValidatorが提供する非推奨APIが削除された
- 2.22. Springの非推奨APIへの対応
- 2.23. Apache Commons Langの非推奨APIへの対応
- 3. ブランクプロジェクトの軽微な修正
|
Note
|
5.10.0.RELEASEから5.11.0.RELEASEの移行手順として説明します。 |
|
Note
|
当移行ガイドと合わせて を一読し、Spring Frameworkの変更を把握することを推奨します。 |
5.11.0での主な変更点は以下の通りです。
-
主要なライブラリのバージョンを更新
-
共通ライブラリの変更
-
ブランクプロジェクトの変更
-
JUnit4からJUnit6への移行
-
Jackson2からJackson3への移行
-
Spring Boot Dependenciesを4.0.2へ更新
-
Spring Frameworkを7.0.3へ更新
-
Spring Securityを7.0.2へ更新
-
Spring Dataを4.0.2へ更新
-
Hibernate ORMを7.2.1.Finalへ更新
-
-
MyBatisを3.5.19、MyBatis Springを4.0.0へ更新
-
ブランクプロジェクトのライブラリ及びMavenプラグインのバージョンを変更
-
[single#708] [multi#771] Update the defined library version
-
[single#714] [multi#777] Upgrading the JDBC driver
-
[single#722] [multi#785] Upgrade Oracle driver version
-
-
機能改善
-
[single#681] [multi#741] Migrating from JUnit4 to Junit5
-
[single#715] [multi#778] Modify the data source settings for the application server
-
[single#689] [multi#753] RequestMatcher Changes.(Boot 4.0.0-M1)
-
[single#695] [multi#757] Removal of Access Module-related APIs and Support for JCL 1.3(Boot 4.0.0-M3)
-
-
logbackのフォーマット変更
-
[single#712] [multi#676] Vulnerability that may result in logs being output that exploit terminal (console) functionality
-
-
軽微な修正
-
[single#697] [multi#775] Change from java.util.Date to java.time
-
[single#298] [multi#738] </bean> is redundant in UserIdMDCPutFilter
-
[single#738] The fix for BeanNameViewResolver is incomplete
-
移行手順は、以下の通りです。
依存ライブラリを更新を実施後、必要に応じて手順を上から順に適用してください。
|
Note
|
凡例 |
| 変更点 | MavenMultiple Projects | MavenSingle Project |
|---|---|---|
必須 |
必須 |
|
任意 |
任意 |
|
任意 |
任意 |
|
必須 |
必須 |
|
条件付き必須 |
条件付き必須 |
|
推奨 |
推奨 |
|
必須 |
必須 |
|
条件付き必須 |
条件付き必須 |
|
必須 |
必須 |
|
任意 |
任意 |
|
条件付き必須 |
条件付き必須 |
|
推奨 |
推奨 |
|
Apache HttpComponents HttpClientのSSL(TLS)ハンドシェイクタイムアウトの設定方法の変更 |
条件付き必須 |
条件付き必須 |
任意 |
任意 |
|
推奨 |
推奨 |
|
条件付き必須 |
条件付き必須 |
|
条件付き必須 |
条件付き必須 |
|
条件付き必須 |
条件付き必須 |
|
条件付き必須 |
条件付き必須 |
|
条件付き必須 |
条件付き必須 |
|
条件付き必須 |
条件付き必須 |
|
条件付き必須 |
条件付き必須 |
|
条件付き必須 |
条件付き必須 |
TERASOLUNA Server Framework for Java (5.x)の共通ライブラリと依存ライブラリを更新してください。
以下に、この手順により更新される代表的な依存ライブラリを示します。
| ライブラリ名 | 更新前バージョン | 更新後バージョン | 備考 |
|---|---|---|---|
TERASOLUNA Server Framework for Java (5.x) Common Library |
5.10.0.RELEASE |
5.11.0.RELEASE |
|
Spring Framework |
6.2.1 |
7.0.3 |
|
Spring Data |
3.4.1 |
4.0.2 |
|
Spring Security |
6.4.2 |
7.0.2 |
|
Spring Test |
6.2.1 |
7.0.3 |
|
MyBatis3 |
3.5.17 |
3.5.19 |
|
MyBatis3 Spring |
3.0.4 |
4.0.0 |
|
Hibernate ORM |
6.6.4.Final |
7.2.1.Final |
|
AOP |
1.9.22.1 |
1.9.25.1 |
|
Logback |
1.5.12 |
1.5.22 |
|
SLF4J |
2.0.16 |
2.0.17 |
|
Jackson2 |
2.18.2 |
2.20.1 |
|
Jackson3 |
- |
3.0.4 |
追加 |
Hibernate Validator |
8.0.2.Final |
9.1.0.Final |
|
Apache Commons Lang |
3.17.0 |
3.19.0 |
|
Apache Commons DBCP |
2.12.0 |
2.13.0 |
|
Open PDF |
1.3.35 |
- |
削除 |
Apache POI |
5.3.0 |
- |
削除 |
Apache HttpClient |
5.4.2 |
5.5.2 |
|
Google Guava |
33.3.1-jre |
33.5.0-jre |
|
Apache Commons Collections |
4.4 |
4.5.0 |
|
Apache Commons IO |
2.18.0 |
2.20.0 |
|
Lombok |
1.18.36 |
1.18.42 |
|
JUnit4 |
4.13.1 |
- |
削除 |
Hamcrest |
2.2 |
- |
削除 |
JUnit6 |
- |
6.0.2 |
追加 |
AssertJ |
- |
3.27.6 |
追加 |
Mockito |
5.14.2 |
5.20.0 |
|
DBUnit |
2.8.0 |
3.0.0 |
[手順が必要なケース]
この手順の適用は必須です。
この更新手順は、Mavenをオンライン環境で使用しており、multi blankまたはsingle blankを使用して作成したプロジェクト向けです。
POMファイルのversionを5.11.0.RELEASEに修正してください。
-
($YOUR_MULTIPLE_PROJECT_ROOT/pom.xml)
-
($YOUR_SINGLE_PROJECT/pom.xml)
<!-- omitted -->
<parent>
<groupId>org.terasoluna.gfw</groupId>
<artifactId>terasoluna-gfw-parent</artifactId>
<version>5.11.0.RELEASE</version> <!-- ### 修正箇所 ### -->
</parent>
<!-- omitted -->この更新手順は、依存ライブラリをインターネットにつながる環境でダウンロードし、ダウンロードした依存ライブラリをオフライン環境のプロジェクトに展開することで、Mavenをオフライン環境で使用しているプロジェクト向けです。
以下に記載する手順を実施してください。
-
オンライン環境
-
ブランクプロジェクトを作成
ガイドラインの記述を参考に、archetype:generateを実行し、5.11.0.RELEASEのブランクプロジェクトを作成してください。 -
依存関係の追加
現行アプリのpom.xmlを確認し、アプリ独自で設定しているdependencyをブランクプロジェクトのpom.xmlに追加してください。
アプリ独自で設定しているdependencyが不明な場合は、現行アプリで採用しているバージョンのブランクプロジェクトも作成して比較してください。 -
ローカルリポジトリへのダウンロード
以下のコマンドを実行し、依存ライブラリおよびMavenビルドに必要となるライブラリやプラグイン等をローカルリポジトリ(repositoryディレクトリ)へダウンロードしてください。mvn -P warpack clean install -Dmaven.repo.local=repository mvn dependency:go-offline -Dmaven.repo.local=repository
-
-
オンライン環境⇒オフライン環境
-
オフライン環境へのコピー
repositoryをオフライン環境の「ユーザのホームディレクトリ/.m2」へコピーしてください。
-
-
オフライン環境
-
POMの修正
オフライン環境のプロジェクトにて、オンライン環境でバージョン更新を実施する場合に記載されている内容と同様に、pom.xmlのバージョン表記を修正してください。 -
ビルドの実行
-
envモジュールのjarファイルをwarファイルに含めない場合
以下のコマンドを実行してください。mvn -P warpack clean install
xxx-env配下に移動し以下のコマンドを実行してください。
mvn -P test-server clean package
-
envモジュールのjarファイルをwarファイルに含める場合
以下のコマンドを実行してください。mvn -P warpack-with-env,test-server clean package
-
-
共通ライブラリが管理するMavenプラグインの最新化を行いました。
最新化されたプラグインのバージョンについては、以下を参照してください。
上記ページに記載のプラグインについては、バージョン指定なしに使用することが可能です。
[手順が必要なケース]
以下のケースに当てはまる場合、ビルドや実行に問題がないことを確認しながら、必要に応じて修正を行ってください。
-
共通ライブラリが提供するプラグインのバージョンから変更したい場合
[修正方法]
プラグインごとに対応方法が異なるため、各公式リファレンスを参照して対応してください。
なお、terasoluna-gfw-parentで定義しているプラグインのバージョンを変更したい場合は、terasoluna-gfw-parentのpom.xmlに定義されたプロパティを自アプリのpom.xmlで上書きします。
例えば Maven Dependency Plugin のバージョンを指定したい場合は以下のように、terasoluna-gfw-parentで定義されたプロパティを上書きします。
-
($YOUR_PROJECT/pom.xml)
<properties>
<!-- omitted -->
<org.apache.maven.plugins.maven-dependency-plugin.version>3.8.1</org.apache.maven.plugins.maven-dependency-plugin.version> <!-- ### 追加箇所 ### -->
</properties>ブランクプロジェクトのpomファイルに記載している PostgreSQL JDBC Driver と Oracle JDBC のバージョン定義を更新しました。
これらのJDBCドライバーは、利用するデータベースおよびJDKとの組み合わせを確認のうえ、適切なバージョンを選択してください。
[手順が必要なケース]
本手順は任意です。
以降では、TERASOLUNA Server Framework for Java 5.11.0.RELEASEの動作検証環境に合わせる形での変更方法を示します。
以下の情報を参照し、適切なバージョンを設定してください。
[修正方法]
pomファイルのプロパティを修正してください。
-
($YOUR_MULTIPLE_PROJECT_ROOT/pom.xml)
-
($YOUR_SINGLE_PROJECT/pom.xml)
<properties>
<!-- omitted -->
<postgresql.version>42.7.9</postgresql.version> <!-- ### 修正箇所 ### -->
<!-- omitted -->
</properties>以下の情報を参照し、適切なバージョンを設定してください。
[修正方法]
pomファイルのプロパティを修正してください。
-
($YOUR_MULTIPLE_PROJECT_ROOT/pom.xml)
-
($YOUR_SINGLE_PROJECT/pom.xml)
<properties>
<!-- omitted -->
<ojdbc.version>23.26.0.0.0</ojdbc.version> <!-- ### 修正箇所 ### -->
<!-- omitted -->
</properties>Spring Security 7以降ではAntPathRequestMatcherとMvcRequestMatcherが削除され、デフォルトのRequestMatcherとしてPathPatternRequestMatcherがパスを解析するようになりました。
[手順が必要なケース]
この手順の適用は必須です。
[修正方法]
PathPatternRequestMatcher(PathPatternParser)では、AntPathRequestMatcherで利用できていた一部のパスの書き方がサポートされていないため、どのようなパス指定を行っていたかによって修正方法が異なります。(対応できるパスについてはこちらを参照してください。)基本的にはPathPatternRequestMatcherの利用を検討し、業務上必要なパス指定が行えない場合に、RegexRequestMatcherの使用を検討してください。
-
【推奨】
PathPatternRequestMatcherを使用する -
RegexRequestMatcherを使用する
ブランクプロジェクトの場合、以下のように修正します。
-
($YOUR_MULTIPLE_PROJECT_WEB/src/main/java/com/example/sample/config/web/SpringSecurityConfig.java)
-
($YOUR_SINGLE_PROJECT/src/main/java/com/example/sample/config/web/SpringSecurityConfig.java)
import static org.springframework.security.web.util.matcher.AntPathRequestMatcher.antMatcher; // ### 削除 ###
// omitted
@Configuration
@EnableWebSecurity
public class SpringSecurityConfig {
// omitted
@Bean
public WebSecurityCustomizer webSecurityCustomizer() {
return web -> web.ignoring().requestMatchers(antMatcher("/resources/**")); // ### 修正前 ###
return web -> web.ignoring().requestMatchers("/resources/**"); // ### 修正後 ###
}
// omitted
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.formLogin(Customizer.withDefaults());
http.logout(Customizer.withDefaults());
http.exceptionHandling(ex -> ex.accessDeniedHandler(accessDeniedHandler()));
http.addFilterAfter(userIdMDCPutFilter(), AnonymousAuthenticationFilter.class);
http.sessionManagement(Customizer.withDefaults());
http.authorizeHttpRequests(authz -> authz.requestMatchers(antMatcher("/**")).permitAll()); // ### 修正前 ###
http.authorizeHttpRequests(authz -> authz.requestMatchers("/**").permitAll()); // ### 修正後 ###
return http.build();
}
// omitted
}ブランクプロジェクトの場合、以下のように修正します。
-
($YOUR_MULTIPLE_PROJECT_WEB/src/main/resources/META-INF/spring/spring-security.xml)
-
($YOUR_SINGLE_PROJECT/src/main/resources/META-INF/spring/spring-security.xml)
<sec:http pattern="/resources/**" request-matcher="ant" security="none" /> <!-- ### 修正前 ### -->
<sec:http pattern="/resources/**" security="none" /> <!-- ### 修正後 ### -->
<sec:http request-matcher="ant"> <!-- ### 修正前 ### -->
<sec:http> <!-- ### 修正後 ### -->
<sec:form-login />
<sec:logout />
<sec:access-denied-handler ref="accessDeniedHandler" />
<sec:custom-filter ref="userIdMDCPutFilter" after="ANONYMOUS_FILTER" />
<sec:session-management />
<sec:intercept-url pattern="/**" access="permitAll" />
</sec:http>PathPatternParserが解釈できないAntパスを使用していた場合は、RegexRequestMatcherを使用するように修正してください。
例えば、Antパスとして/hoge/**/fooのようなパスを使用していた場合は、RegexRequestMatcherを使用して/hoge/.*/fooのように修正します。
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) {
// omitted
http.authorizeHttpRequests(authz -> authz
.requestMatchers(new RegexRequestMatcher("/hoge/.*/foo", "GET")).hasRole("ACCOUNT_MANAGER")
);
// omitted
}Spring Framework 7以降ではSpring TestContext FrameworkのJUnit4向けの機能が非推奨となり、以降のバージョンでサポートを終了する旨が記載されたことを受け、ガイドラインで案内しているJUnitコードについては、JUnit6への移行を行いました。
また、これに伴って、ガイドラインで例として使用するアサーションライブラリをAssertJに変更しました。
フレームワークとしては、アサーションライブラリについて推奨等を定めておりませんので、任意のアサーションライブラリをご利用ください。以降ではAssertJを使用する場合と、Hamcrestを使用する場合の例を示しています。
[手順が必要なケース]
以下に当てはまる場合、必ず修正してください。
-
Spring TestContext FrameworkのJUnit4向けの機能を使用している
|
Note
|
JUnit4の機能のみを使用している場合は、JUnit6への移行は必須ではありませんが、JUnit4はメンテナンスモードであるため、JUnit6への移行を推奨します。 |
[修正方法]
-
pomファイルの修正
-
テストコードの修正
<!-- omitted -->
<!-- ### 削除 - 開始 ### -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
<!-- ### 削除 - 終了 ### -->
<!-- ### 追加 - 開始 ### -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
<!-- ### 追加 - 終了 ### -->
<!-- omitted --><!-- omitted -->
<!-- ### 削除 - 開始 ### -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
<!-- ### 削除 - 終了 ### -->
<!-- ### 追加 - 開始 ### -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
<!-- ### 追加 - 終了 ### -->
<!-- omitted -->以下の対応が必要となります。
-
パッケージ名の変更
-
アノテーションの変更
-
アサーションの変更
-
ロジックの一部変更
JUnitそのものの移行に関してはMigrating from JUnit 4を参照してください。
ここでは、上記Migrating from JUnit 4に記載されていないSpring Testに関する変更点を説明します。
TestContextフレームワークの機能をJUnitフレームワークに統合する方法が変更されました。
JUnit4では、TestContextフレームワークの機能を使用するために、テストクラスで@RunWith(SpringRunner.class)を指定する必要がありましたが、JUnit6では、テストクラスで@ExtendWith(SpringExtension.class)を指定する必要があります。
@RunWith(SpringJUnit4ClassRunner.class) // ### 修正前 ###
@ExtendWith(SpringExtension.class) // ### 修正後 ###
@ContextConfiguration(classes = {MyConfig.class})
public class MyTests {
// omitted
}@ExtendWithと@ContextConfigurationを統合し@SpringJUnitConfigを使用することもできます。
@SpringJUnitConfig(classes = {MyConfig.class})
public class MyTests {
// omitted
}|
Note
|
|
Springのログライブラリとして、Spring JCLが廃止され、Apache Commons Logging 1.3(JCL1.3)に移行されました。
これに伴い、Log4j2を依存関係に含んでいる場合にLog4j2が優先して使用されるようになるため、SLF4Jを優先的に使用するための設定が必要となります。
詳しくはJCL(Apache Commons Logging)のログ出力についてを参照してください。
[手順が必要なケース]
本手順の適用を推奨します。
[修正方法]
commons-logging.propertiesを作成します。
commons-logging.propertiesを作成することにより、Slf4jLogFactoryがLog4jApiLogFactoryより先に呼び出されるようになります。
-
($YOUR_MULTIPLE_PROJECT_WEB/src/main/resources/commons-logging.properties)
-
($YOUR_SINGLE_PROJECT/src/main/resources/commons-logging.properties)
# Force Slf4jLogFactory when JCL logs are invoked
org.apache.commons.logging.LogFactory=org.apache.commons.logging.impl.Slf4jLogFactory画面認可用のDefaultWebSecurityExpressionHandlerなどのAccess系APIが別モジュール(spring-security-access)へ切り出されました。
[手順が必要なケース]
この手順の適用は必須です。
[修正方法]
-
JavaConfigを使用している場合は、DefaultWebSecurityExpressionHandlerを削除してください。
-
XMLConfigを使用している場合
-
画面認可を使用している場合は、Accessモジュールの依存関係を追加してください。
-
画面認可を使用していない場合は、DefaultWebSecurityExpressionHandlerの設定を削除してください。
-
ブランクプロジェクトの設定からDefaultWebSecurityExpressionHandlerを削除します。なお、代替機能は@EnableMethodSecurityアノテーション(@EnableWebSecurityを設定していれば自動的に設定される)を使用することで自動的に必要なBeanが作成されるため、削除するのみで問題ありません。
-
($YOUR_MULTIPLE_PROJECT_WEB/src/main/java/com/example/sample/config/SecurityConfig.java)
-
($YOUR_SINGLE_PROJECT/src/main/java/com/example/sample/config/SecurityConfig.java)
@Configuration
@EnableWebSecurity
public class SpringSecurityConfig {
// omitted
// ### 削除 - 開始 ###
/**
* Configure {@link DefaultWebSecurityExpressionHandler} bean.
* @return Bean of configured {@link DefaultWebSecurityExpressionHandler}
*/
@Bean("webSecurityExpressionHandler")
public DefaultWebSecurityExpressionHandler webSecurityExpressionHandler() {
return new DefaultWebSecurityExpressionHandler();
}
// ### 削除 - 終了 ###
// omitted
}<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %>
<sec:authorize access="hasRole('ADMIN')">
<h2>Admin Menu</h2>
<!-- omitted -->
</sec:authorize>上記のような画面認可の使用有無により対応が異なります。
画面認可を使用している場合は、pom.xmlにAccessモジュールの依存関係を追加してください。
-
($YOUR_MULTIPLE_PROJECT_WEB/pom.xml)
-
($YOUR_SINGLE_PROJECT/pom.xml)
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-access</artifactId>
</dependency>|
Note
|
|
画面認可を使用していない場合は、以下の設定を削除してください。
-
($YOUR_MULTIPLE_PROJECT_WEB/src/main/resources/spring/spring-security.xml)
-
($YOUR_SINGLE_PROJECT/src/main/resources/spring/spring-security.xml)
<bean id="webSecurityExpressionHandler" class="org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler" />認証処理を行うSpring Security Filterの起動判定は、PathPatternRequestMatcherがキャッシュしたRequestPathを用いて行われます。
RequestMatcherのパス解析方法の変更では、RequestMatcherがPathPatternRequestMatcherへ変更されたことを記載しましたが、この影響によりForwardした先のリクエストパスが認証パスの場合に、PathPatternRequestMatcherにキャッシュされているRequestPathがForward前のままとなっており、認証処理が動かない(Spring Security Filterが起動しない)可能性があります。
なお、本事象はXMLConfigだけで発生し、JavaConfigでは問題ありません。
詳しくは認証時の入力チェックを参照してください。
[手順が必要なケース]
以下のケースに当てはまる場合、必ず修正を行ってください。
-
XMLConfigを使用している
-
ハンドラメソッドから認証パスへForwardしている
[修正方法]
org.springframework.web.filter.ServletRequestPathFilterをSpringSecurityFilterChainの前に配置します。
以下はweb.xmlでFilterを設定する例となります。
-
web.xml
<filter>
<filter-name>ServletRequestPathFilter</filter-name>
<filter-class>org.springframework.web.filter.ServletRequestPathFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>ServletRequestPathFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<!-- omitted -->|
Note
|
SpringがJavaConfigをベースに開発を進めていることから、当問題のようにXMLConfigのみに問題が発生するケースが今後も出てくる可能性があるため、JavaConfigへの移行を推奨します。 |
ログフォーマットを変更することで、制御文字の出力抑止を行ってください。
本手順を行うことで、ログをコンソール(ターミナル)で閲覧(表示)する際に、ユーザの悪意のある入力等によって、コンソール(ターミナル)が持つ特殊な機能が呼び出されることを防ぐことができるようになります。
[手順が必要なケース]
本手順の適用は必須です。
[修正方法]
logback.xmlに設定されているログフォーマット上、外部からの入力値が埋め込まれる可能性がある部分に対し、一部(水平タブ, CR, LF)を除く制御文字(C0制御文字(ASCII制御文字)とC1制御文字(U+0080~U+009F))を別の文字(あるいは文字列)に置換するよう設定してください。制御文字の置換は、
%replace(…){'[\p{IsControl}&&[^\t\r\n]]','<CTRL>'}
※「…」は、外部からの入力値が埋め込まれる可能性がある部分(「%msg」等)
のような記法で設定できます。
ブランクプロジェクトがデフォルトで提供しているlogback.xmlでは、
-
%X{X-Track} -
%msg -
%xEx
を置換の対象としています。これら以外に外部からの入力値が埋め込まれる可能性がある部分がある場合は、適宜修正してください。
-
($YOUR_MULTIPLE_PROJECT_ENV/src/main/resources/logback.xml)
-
($YOUR_SINGLE_PROJECT/src/main/resources/logback.xml)
<configuration>
<!-- omitted -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern><![CDATA[date:%d{yyyy-MM-dd HH:mm:ss}\tthread:%thread\tX-Track:%X{X-Track}\tlevel:%-5level\tlogger:%-48logger{48}\tmessage:%replace(%msg){'(\r\n|\r|\n)','$1 '}%n%replace(%replace(%xEx){'(\r\n|\r|\n)','$1 '}){' $',''}%nopex]]></pattern> <!-- ### 修正前 ### -->
<pattern><![CDATA[date:%d{yyyy-MM-dd HH:mm:ss}\tthread:%thread\tX-Track:%replace(%X{X-Track}){'[\p{IsControl}&&[^\t\r\n]]','<CTRL>'}\tlevel:%-5level\tlogger:%-48logger{48}\tmessage:%replace(%replace(%msg){'[\p{IsControl}&&[^\t\r\n]]','<CTRL>'}){'(\r\n|\r|\n)','$1 '}%n%replace(%replace(%replace(%xEx){'[\p{IsControl}&&[^\t\r\n]]','<CTRL>'}){'(\r\n|\r|\n)','$1 '}){' $',''}%nopex]]></pattern> <!-- ### 修正後 ### -->
</encoder>
</appender>
<appender name="APPLICATION_LOG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- omitted -->
<encoder>
<charset>UTF-8</charset>
<pattern><![CDATA[date:%d{yyyy-MM-dd HH:mm:ss}\tthread:%thread\tX-Track:%X{X-Track}\tlevel:%-5level\tlogger:%-48logger{48}\tmessage:%replace(%msg){'(\r\n|\r|\n)','$1 '}%n%replace(%replace(%xEx){'(\r\n|\r|\n)','$1 '}){' $',''}%nopex]]></pattern> <!-- ### 修正前 ### -->
<pattern><![CDATA[date:%d{yyyy-MM-dd HH:mm:ss}\tthread:%thread\tX-Track:%replace(%X{X-Track}){'[\p{IsControl}&&[^\t\r\n]]','<CTRL>'}\tlevel:%-5level\tlogger:%-48logger{48}\tmessage:%replace(%replace(%msg){'[\p{IsControl}&&[^\t\r\n]]','<CTRL>'}){'(\r\n|\r|\n)','$1 '}%n%replace(%replace(%replace(%xEx){'[\p{IsControl}&&[^\t\r\n]]','<CTRL>'}){'(\r\n|\r|\n)','$1 '}){' $',''}%nopex]]></pattern> <!-- ### 修正後 ### -->
</encoder>
</appender>
<appender name="MONITORING_LOG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- omitted -->
<encoder>
<charset>UTF-8</charset>
<pattern><![CDATA[date:%d{yyyy-MM-dd HH:mm:ss}\tX-Track:%X{X-Track}\tlevel:%-5level\tmessage:%replace(%msg){'(\r\n|\r|\n)','$1 '}%n%replace(%replace(%xEx){'(\r\n|\r|\n)','$1 '}){' $',''}%nopex]]></pattern> <!-- ### 修正前 ### -->
<pattern><![CDATA[date:%d{yyyy-MM-dd HH:mm:ss}\tX-Track:%replace(%X{X-Track}){'[\p{IsControl}&&[^\t\r\n]]','<CTRL>'}\tlevel:%-5level\tmessage:%replace(%replace(%msg){'[\p{IsControl}&&[^\t\r\n]]','<CTRL>'}){'(\r\n|\r|\n)','$1 '}%n%replace(%replace(%replace(%xEx){'[\p{IsControl}&&[^\t\r\n]]','<CTRL>'}){'(\r\n|\r|\n)','$1 '}){' $',''}%nopex]]></pattern> <!-- ### 修正後 ### -->
</encoder>
</appender>
<!-- omitted -->
</configuration>DataSourceInitializerおよびTransactionManagerに設定するDataSourceをメソッド参照から@Beanメソッド引数による依存性注入へ変更しました。
[手順が必要なケース]
本手順の適用は任意です。
[修正方法]
以下のように修正してください。
-
($YOUR_MULTIPLE_PROJECT_ENV/src/main/java/com/example/sample/config/app/ProjectNameEnvConfig.java)
-
($YOUR_SINGLE_PROJECT/src/main/java/com/example/sample/config/app/ProjectNameEnvConfig.java)
@Configuration
public class ProjectNameEnvConfig {
// omitted
@Bean
public DataSourceInitializer dataSourceInitializer() { // ### 修正前 ###
public DataSourceInitializer dataSourceInitializer(DataSource dataSource) { // ### 修正後 ###
DataSourceInitializer bean = new DataSourceInitializer();
bean.setDataSource(dataSource()); // ### 修正前 ###
bean.setDataSource(dataSource); // ### 修正後 ###
// omitted
}
// omitted
@Bean("transactionManager")
public TransactionManager transactionManager() { // ### 修正前 ###
public TransactionManager transactionManager(DataSource dataSource) { // ### 修正後 ###
DataSourceTransactionManager bean = new DataSourceTransactionManager();
bean.setDataSource(dataSource()); // ### 修正前 ###
bean.setDataSource(dataSource); // ### 修正後 ###
bean.setRollbackOnCommitFailure(true);
return bean;
}
// omitted
@Bean("dataSource")
public DataSource dataSource() {
// omitted
}
}DoS攻撃への対応のため、マルチパート数の最大数及びヘッダサイズが段階的に調整されました。
-
-
CVE-2023-28709が対応されました。
-
maxParameterCountのデフォルト値が10000から1000に変更されました。
-
-
-
CVE-2025-48988の対応で
maxPartCountが追加されました。デフォルト値は10です。(次のTomcat11.0.9で変更されています。) -
CVE-2025-48976の対応で
maxPartHeaderSizeが追加されました。パラメータ追加前は10KB固定でしたが、デフォルト値は512Bとなりました。
-
-
-
maxPartCountのデフォルト値が10から50に変更されました
-
また、これらのパラメータを制御するためにParameterLimitValveが追加されました。
[手順が必要なケース]
アプリケーションサーバーとしてTomcatを使用している場合は、上記のパラメータについて、必要に応じて見直しを行ってください。
なお、使用するTomcatのバージョンに応じてデフォルト値が異なるため、使用するTomcatのデフォルト値を確認してください。
[修正方法]
ParameterLimitValveの設定を追加またはConnectorの設定を変更し、マルチパートリクエストに関する上限値を見直してください。
ParameterLimitValveを利用した上限値の設定またはserver.xmlのConnector要素を利用したパラメータ指定を参考に、Tomcatの設定を変更してください。
RestTemplateは将来的に廃止されることが宣言されており、移行先としてはRestClientが案内されています。
この案内を受け、TERASOLUNAでもRestClientへの移行を推奨します。
[手順が必要なケース]
本手順の適用を推奨します。
[修正方法]
移行に関しては、ガイドラインにRestTemplateとRestClientの設定の対比を記載しているため、ガイドラインを参照してください。
なお、RestClientはBuilderパターンでの設定のみが提供されているため、ガイドラインではJavaConfigのみ設定例を示しています。XMLConfigの場合は引き続きRestTemplateを使用するか、JavaConfigへの移行を検討してください。
Apache HttpComponents HttpClientのHTTPCLIENT-2386の対応により、SSL(TLS)ハンドシェイクタイムアウトの設定方法が変更されました。
この対応に伴い、SocketConfig.Builder#setSoTimeoutを使用してSSL(TLS)ハンドシェイクタイムアウトを設定することができなくなりました。
SSL(TLS)ハンドシェイクタイムアウトを設定するには、TlsConfig.Builder#setHandshakeTimeoutを使用して設定する必要があります。
[手順が必要なケース]
以下のケースに当てはまる場合、必ず修正を行ってください。
-
SocketConfig.Builder#setSoTimeoutを使用して、SSL(TLS)ハンドシェイクタイムアウトを設定している。
[修正方法]
HttpComponentsClientHttpRequestFactoryを生成する際に設定するPoolingHttpClientConnectionManagerの定義を修正します。
SocketConfig.Builder#setSoTimeoutに記載していた設定を、TlsConfig.Builder#setHandshakeTimeoutに追加してください。
なお、SoTimeoutはソケットタイムアウトとして引き続き設定する必要があります。(デフォルト値は3分です。)
下記のコードはガイドラインで案内している設定例となります。業務要件に応じ適切な値を設定してください。
PoolingHttpClientConnectionManager connectionManager = PoolingHttpClientConnectionManagerBuilder.create()
.setTlsSocketStrategy(new DefaultClientTlsStrategy(sslContext))
.setDefaultTlsConfig(
TlsConfig.custom()
.setSupportedProtocols(TLS.V_1_3, TLS.V_1_2)
.setHandshakeTimeout(Timeout.ofMilliseconds(1L)) // ### 追加箇所 ###
.build())
.setDefaultSocketConfig(
SocketConfig.custom()
.setSoTimeout(Timeout.ofMinutes(1L)) // ### 修正箇所 ###
.build())
.setMaxConnTotal(1)
.setMaxConnPerRoute(1)
.setPoolConcurrencyPolicy(PoolConcurrencyPolicy.STRICT)
.setConnPoolPolicy(PoolReusePolicy.LIFO)
.setDefaultConnectionConfig(
ConnectionConfig.custom()
.setTimeToLive(TimeValue.ofMinutes(1L))
.setConnectTimeout(Timeout.ofSeconds(5L))
.build())
.build();RestTemplateの実装方法としてSimpleClientHttpRequestFactoryを利用した実装をガイドラインで紹介していましたが、他のClientHttpRequestFactoryの実装と比較すると機能が限定されているため、HttpComponentsClientHttpRequestFactoryを推奨設定に変更しました。
それに伴い、ガイドラインの実装例もHttpComponentsClientHttpRequestFactoryを利用した実装に変更しています。
[手順が必要なケース]
この手順は任意です。
現時点の実装で通信要件を満たせている場合は、本手順の適用は不要です。
[修正方法]
RestTemplateのコンストラクタに、HttpComponentsClientHttpRequestFactoryを設定するように変更してください。
HttpComponentsClientHttpRequestFactoryを利用した通信設定に関しては、ガイドラインを参照してください。
@Bean("restTemplate")
public RestTemplate restTemplate() {
return new RestTemplate(); // ### 修正前 ###
return new RestTemplate(new HttpComponentsClientHttpRequestFactory()); // ### 修正後 ###
}Jackson3がリリースされたことを受け、Spring Frameworkが提供するJackson2用のMessageConverterが非推奨となりました。
これに伴い、Jackson3への移行を推奨します。
なお、Jackson2からJackson3への移行に伴い、Jacksonに数多くの変更が発生しています。
詳しくはSpring#33798およびIntroducing Jackson 3 support in Springを参照してください。
[手順が必要なケース]
本手順の適用を推奨します。
[修正方法]
以下の対応を行ってください。
-
MessageConverterの設定(Springの提供するJackson3向けのMessageConverterの設定をデフォルトから変更する場合)
-
Jackson3に対応したAPIを使用するようコードの修正(アプリケーション側で直接Jackson2に依存するコードを書いている場合)
|
Note
|
Jackson3ではBuilderパターンのみが提供されているため、ガイドラインではJavaConfigでの定義例のみを示しています。 |
Jackson3用の依存関係を追加したことにより、Springが使用するデフォルトのMessageConverterがJackson3に対応したものに変更されました。
このため、デフォルトで使用する場合は特に設定は必要ありませんが、独自のMessageConverterを定義している場合は、Jackson3用のMessageConverterを定義する必要があります。
以下は、ガイドラインに記載していたJackson2用のMessageConverterの設定を修正する例となります。
-
修正前
@Bean("jsonMessageConverter")
public MappingJackson2HttpMessageConverter jsonMessageConverter(
ObjectMapper objectMapper) {
MappingJackson2HttpMessageConverter bean = new MappingJackson2HttpMessageConverter();
bean.setObjectMapper(objectMapper);
return bean;
}
@Bean("objectMapper")
public ObjectMapper objectMapper() {
Jackson2ObjectMapperFactoryBean bean = new Jackson2ObjectMapperFactoryBean();
bean.setDateFormat(stdDateFormat());
bean.afterPropertiesSet();
return bean.getObject();
}
@Bean
public StdDateFormat stdDateFormat() {
return new StdDateFormat();
}
@Override
public void configureMessageConverters(
List<HttpMessageConverter<?>> converters) {
converters.add(jsonMessageConverter(objectMapper()));
}-
修正後
当修正例は、下記設定をデフォルトから変更する場合の例となります。
デフォルトのMessageConverterを使用する場合は、下記設定はすべて不要となります。
-
MapperFeature.DEFAULT_VIEW_INCLUSION : enable(デフォルトdisable)
-
@JsonViewでグループ分けされていないプロパティも出力する
-
-
DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES : enable(デフォルトdisable)
-
不明なプロパティが存在する場合に例外をスローする
-
設定できるオプションに関してはReference manualを参照してください。
|
Note
|
|
なお、Easier message converters configuration with HttpMessageConvertersに記載されている通り、configureMessageConverters(List<HttpMessageConverter<?>>)は非推奨となっているため、configureMessageConverters(HttpMessageConverters.ServerBuilder)を使用してください。
@Override
public void configureMessageConverters(HttpMessageConverters.ServerBuilder builder) {
builder.registerDefaults().withJsonConverter(jsonMessageConverter());
}
@Bean("jsonMessageConverter")
public JacksonJsonHttpMessageConverter jsonMessageConverter() {
JacksonJsonHttpMessageConverter bean = new JacksonJsonHttpMessageConverter(jsonMapper());
return bean;
}
@Bean("jsonMapper")
public JsonMapper jsonMapper() {
return JsonMapper.builder().enable(MapperFeature.DEFAULT_VIEW_INCLUSION)
.enable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
.enable(DateTimeFeature.WRITE_DATES_AS_TIMESTAMPS).build();
}パッケージ名の変更や発生する例外の変更など、修正は多岐にわたります。
Jackson 3 Migration Guideに従い修正してください。
Trailing Slash(ハンドラメソッドのパターンがhogeに対しhoge/でアクセス可能とする)やSuffix Pattern Matching(ハンドラメソッドのパターンがhogeに対しhoge.*(任意の拡張子)でアクセス可能とする)に関する機能が削除されました。
[手順が必要なケース]
以下のケースのいずれかに当てはまる場合、必要に応じて修正を行ってください。
-
Trailing Slashを使用している
-
Suffix Pattern Matchingを使用している
[修正方法]
Trailing SlashやSuffix Pattern Matchingは多くの問題を抱えていることが指摘されており、PathPatternParserでは機能が提供されていません。
そのため、URLパターンを明示的に指定するように修正してください。
例えば、hogeとhoge/の両方でアクセス可能にしたい場合は、以下のようになります。(Suffix Pattern Matchingも同様に、必要なパターンを明示的に指定してください。)
@GetMapping({ "hoge", "hoge/" })
public String sample() {
// omitted
}HttpHeadersはMapやMultiValueMapとして処理することが可能でしたが、keyを大文字・小文字を区別してしまうため、重複ヘッダを生成してしまう問題がありました。
そのため、Spring#33913の対応により、HttpHeadersをMapやMultiValueMapとして処理するのではなく、専用のAPIを使用するように変更されました。
[手順が必要なケース]
以下のケースに当てはまる場合、必要に応じて修正を行ってください。
-
HttpHeadersをMapやMultiValueMapとして処理している
[修正方法]
JavaDocを参照し、HttpHeadersのAPIを使用してヘッダを処理するように修正してください。
ResponseErrorHandler#handleError(ClientHttpResponse)が削除されました。
[手順が必要なケース]
以下のいずれかのケースに当てはまる場合、必要に応じて修正を行ってください。
-
ResponseErrorHandlerを実装している -
DefaultResponseErrorHandlerを継承している
[修正方法]
以下は、DefaultResponseErrorHandlerを継承している場合の修正例となります。
ResponseErrorHandler#handleError(URI, HttpMethod, ClientHttpResponse)をオーバーライドしてエラーハンドリングを行うように修正してください。(ResponseErrorHandlerの場合も同様の修正となります。)
public class CustomErrorHandler extends DefaultResponseErrorHandler {
// ### 削除 - 開始 ###
@Override
public void handleError(ClientHttpResponse response) throws IOException {
// omitted
}
// ### 削除 - 終了 ###
@Override
public void handleError(URI url, HttpMethod method, ClientHttpResponse response) throws IOException {
// Error Handling
}
}Bean名の重複を許可するための設定(enforceUniqueMethods)はデフォルトでfalseでしたが、@Configurationクラス内でBean名が重複している場合はオーバーライドされていました。
この挙動が変更され、@Configurationクラス内でもBean名の重複が許容されなくなりました。
[手順が必要なケース]
以下のケースに当てはまる場合、必要に応じて修正を行ってください。
-
@Configurationクラス内でBean名の重複が発生している
[修正方法]
@Configurationクラス内でBean名の重複が発生している場合は、Bean名を変更するなどして重複が発生しないように修正してください。
DaoAuthenticationProviderのデフォルトコンストラクタが削除されました。
[手順が必要なケース]
以下のケースに当てはまる場合、必要に応じて修正を行ってください。
-
DaoAuthenticationProviderのデフォルトコンストラクタを使用している
XMLConfigの場合は、authentication-providerを使用するため、本手順の対象外となります。
[修正方法]
DaoAuthenticationProvider(UserDetailsService)コンストラクタを使用するように修正してください。
-
($YOUR_MULTIPLE_PROJECT_WEB/src/main/java/com/example/sample/config/SpringSecurityConfig.java)
-
($YOUR_SINGLE_PROJECT/src/main/java/com/example/sample/config/SpringSecurityConfig.java)
-
修正前
@Bean("authenticationProvider")
public AuthenticationProvider authenticationProvider(
@Qualifier("passwordEncoder") PasswordEncoder passwordEncoder) {
DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
authProvider.setUserDetailsService(accountUserDetailsService());
authProvider.setPasswordEncoder(passwordEncoder);
return authProvider;
}-
修正後
@Bean("authenticationProvider")
public AuthenticationProvider authenticationProvider(
@Qualifier("passwordEncoder") PasswordEncoder passwordEncoder) {
DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider(accountUserDetailsService());
authProvider.setPasswordEncoder(passwordEncoder);
return authProvider;
}@Email,@NotBlank,@NotEmptyなど、HibernateValidatorが提供する一部の非推奨APIが削除されました。
[手順が必要なケース]
以下のケースに当てはまる場合、必要に応じて修正を行ってください。
-
上記の非推奨APIを利用している
[修正方法]
Jakarta Validationが提供する同等のAPIを使用するよう修正してください。
例えば、@Emailを使用している場合は、以下のようになります。
import org.hibernate.validator.constraints.Email; // ### 修正前 ###
import jakarta.validation.constraints.Email; // ### 修正後 ###
// omitted
public class SampleForm {
@Email
private String email;
// omitted
}この移行ガイドラインで取り扱っていない、開発ガイドラインの記載の範囲外のSpringの非推奨APIについては、以下を参照してください。
ダウンロードのViewを提供するorg.springframework.web.servlet.view.documentパッケージが非推奨となりました。
これに伴い、ガイドラインで案内している以下のダウンロードViewの実装例を、TERASOLUNAが提供するAPIを使用する実装例に変更しました。
-
org.springframework.web.servlet.view.document.AbstractPdfView -
org.springframework.web.servlet.view.document.AbstractXlsView
[手順が必要なケース]
以下のケースに当てはまる場合、必要に応じて修正を行ってください。
-
上記の非推奨APIを利用している
[修正方法]
代替機能として、TERASOLUNA共通フレームワークが提供するorg.terasoluna.gfw.web.download.AbstractFileDownloadViewを使用するよう修正してください。
AbstractFileDownloadViewの使用方法については、ガイドラインを参照してください。
Apache Commons Lang 3.18.0 から下記のAPIが非推奨となりました。
-
StringUtils#startsWith(CharSequence, CharSequence…)メソッド -
StringUtils#endsWith(CharSequence, CharSequence)メソッド -
StringUtils#removeEnd(String, String)メソッド -
他多数
[手順が必要なケース]
以下のケースに当てはまる場合、必要に応じて修正を行ってください。
-
上記の非推奨APIを利用している
[修正方法]
Javadocを参考に、非推奨APIを代替APIに置き換えてください。
ブランクプロジェクトに軽微な修正を行いました。
通常のアプリケーションプロジェクトではこれらの修正は必要ないと思われるため、移行ガイドラインの手順からは外していますが、必要に応じてご参照ください。
ViewResolverの設定がmulti blankとsingle blankで異なっていたため、BeanNameViewResolverを追加して統一しました。
-
SpringMvcConfig.java
@EnableAspectJAutoProxy
@EnableWebMvc
@Configuration
public class SpringMvcConfig implements WebMvcConfigurer {
// omitted
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
registry.beanName();
// omitted
}-
spring-mvc.xml
<mvc:view-resolvers>
<mvc:bean-name />
<!-- omitted -->
</mvc:view-resolvers>ブランクプロジェクトのHelloController.javaで使用している日付関連のクラスを、java.util.Dateからjava.time.LocalDateTimeへ変更しました。
-
HelloController.java
@Controller
public class HelloController {
// omitted
@GetMapping(value = "/")
public String home(Locale locale, Model model) {
logger.info("Welcome home! The client locale is {}.", locale);
// ### 修正前 ###
Date date = new Date();
DateFormat dateFormat =
DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale);
String formattedDate = dateFormat.format(date);
// ### 修正前 ###
// ### 修正後 ###
LocalDateTime dateTime = LocalDateTime.now();
DateTimeFormatter formatter = DateTimeFormatter
.ofLocalizedDateTime(FormatStyle.LONG, FormatStyle.MEDIUM).withLocale(locale);
String formattedDate = dateTime.format(formatter);
// ### 修正後 ###
model.addAttribute("serverTime", formattedDate);
return "welcome/home";
}-
application-messages.properties
### 修正前 ###
typeMismatch.java.util.Date="{0}" is not a date.
### 修正後 ###
typeMismatch.java.time.LocalDateTime="{0}" is not a date.冗長となっていた</bean>を修正しました。
-
spring-security.xml
<!-- ## 修正前 ## -->
<bean id="userIdMDCPutFilter" class="org.terasoluna.gfw.security.web.logging.UserIdMDCPutFilter">
</bean>
<!-- ## 修正後 ## -->
<bean id="userIdMDCPutFilter" class="org.terasoluna.gfw.security.web.logging.UserIdMDCPutFilter" />