如何使用 Spring Boot 修復瀏覽器中不顯示的 H2 控制台
1.概述
H2 控制台作為 H2 資料庫的圖形使用者介面 (GUI) 用戶端,讓我們透過網頁查詢資料庫。但是,我們可能會遇到控制台顯示空白頁的問題,特別是當我們的類別路徑中存在 Spring Security 依賴項時。
在本教程中,我們將模擬此問題並學習如何透過在 Spring Security 中配置X-Frame-Options
標頭來解決它。
2. 理解和模擬錯誤
H2 資料庫有助於快速進行原型設計,因為它具有大多數生產級 SQL 伺服器的屬性。但是,當將 H2 資料庫與 Spring Security 一起使用時,瀏覽器中對 H2 控制台的存取會自動受到限制。
發生這種情況是因為 H2 控制台是在<iframe>
中呈現的,而 Spring Security 預設會停用該功能以防止諸如點擊劫持之類的網路攻擊。
在點擊劫持中,惡意網站將目標網站嵌入或覆蓋在可點擊元素(例如框架或按鈕)下,誘騙使用者與惡意內容互動。安全網站實施配置以防止內容在框架中呈現。
讓我們透過設定一個具有 Spring Security 依賴項的簡單 Spring Boot 專案來模擬此錯誤。
2.1. Maven 依賴項
首先,讓我們將spring-boot-starter-web
和spring-boot-starter-security
依賴項新增到pom.xml
檔:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>3.4.4</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
<version>3.4.4</version>
</dependency>
spring-boot-starter-web
依賴項帶有嵌入式伺服器,使我們能夠建立 Web 應用程式。
此外, spring-boot-starter-security
依賴項有助於在典型的 Spring Boot 應用程式中對端點進行身份驗證和授權。當未定義自訂使用者詳細資料時,它會在應用程式啟動時預設產生登入憑證:
- 使用者名稱 –
user
- 密碼 – 控制台中列印的隨機值
接下來,讓我們將H2 資料庫相依性新增至pom.xml
:
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>2.3.232</version>
</dependency>
H2 依賴項提供了一個非常適合快速原型設計的嵌入式資料庫。
2.2.資料庫配置
接下來,讓我們在application.properties
檔案中設定資料庫連線:
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=password
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.h2.console.enabled=true
儘管 Spring Boot 會自動配置資料庫,但我們定義自己的配置來覆蓋預設配置,以實現更好的控制。
預設情況下, spring.h2.console.enable
屬性為false
。我們將其設為true
以啟用 H2 Web 控制台。
2.3.查看控制台
啟用 Spring Security 後,所有端點(包括「 /h2-console/**
」)預設都需要身份驗證。但是,讓我們定義一個名為SecurityConfig
的類別用於自訂配置:
@Configuration
class SecurityConfig {
@Bean
SecurityFilterChain configure(HttpSecurity http) throws Exception {
http.csrf(csrf -> csrf.ignoringRequestMatchers("/h2-console/**"))
.authorizeHttpRequests(auth -> auth
.anyRequest().authenticated())
.formLogin(withDefaults());
return http.build();
}
}
在上面的配置中,我們保留預設的身份驗證和表單登入行為,但禁用「 /h2-console/**
」的 CSRF 保護,以避免 HTTP 403 錯誤。
接下來,讓我們執行我們的應用程式並檢查http://localhost:8080/h2-console.Â
它將我們重定向到Spring Security的登入頁面,我們在那裡使用預設產生的憑證。
登入後,我們將重定向到 H2 控制台的資料庫登入頁面:
然而,當我們嘗試登入時,我們得到一個空白頁面:
導致此錯誤的原因是,H2 控制台使用<iframe>
標籤呈現,而Spring Security 預設透過X-Frame-Options
標頭阻止該標籤。
3.透過停用X-Frame-Options修復錯誤
登入控制台後,頁面無法載入重要元件。我們可以透過停用X-Frame-Options
標頭或僅允許來自相同來源的幀來解決此問題。
3.1.使用frameOptions()
全域停用框架保護
如果應用程式不適用於生產用途,我們可以使用frameOptions():
停用X-Frame-Options
:
@Bean
SecurityFilterChain configure(HttpSecurity http) throws Exception {
http.csrf(csrf -> csrf.ignoringRequestMatchers("/h2-console/**"))
.headers(headers -> headers.frameOptions(HeadersConfigurer.FrameOptionsConfig::disable))
.authorizeHttpRequests(auth -> auth
.anyRequest().authenticated())
.formLogin(withDefaults());
return http.build();
}
在這裡,我們在http
實例上使用headers()
方法來允許框架載入。
現在讓我們看看頁面:
此方法解決了問題,但它在全域範圍內禁用了X-Frame-Options
。
3.2.配置同源存取的框架選項
雖然之前的解決方案有效,但全域停用X-Frame-Options
標頭並不理想,因為它會使應用程式面臨潛在的點擊劫持攻擊。相反,我們可以只允許來自同一來源的幀:
@Bean
SecurityFilterChain configure(HttpSecurity http) throws Exception {
http.csrf(csrf -> csrf.ignoringRequestMatchers("/h2-console/**"))
.headers(headers -> headers.frameOptions(HeadersConfigurer.FrameOptionsConfig::sameOrigin))
.authorizeHttpRequests(auth -> auth
.anyRequest().authenticated())
.formLogin(withDefaults());
return http.build();
}
在這裡,我們改變rameOptions()
以僅允許同源應用程式。
調整這樣的安全配置,只允許在同一來源內進行框架,可以降低點擊劫持的風險。
4. 結論
本文我們模擬了在瀏覽器中存取H2控制台時出現的空白頁錯誤,並透過設定Spring Security中的frameOptions()
設定來解決這個問題。此外,我們還了解如何在開發過程中全域停用X-Frame-Options
並將其限制為相同來源以獲得更好的安全性。
與往常一樣,範例的完整原始程式碼可在 GitHub 上找到。