1. 概述

H2 控制台是 H2 数据库的图形化界面(GUI)客户端,允许我们通过网页查询数据库。但当项目中存在 Spring Security 依赖时,可能会遇到控制台显示空白页面的问题。

本文将模拟这个问题,并通过配置 Spring Security 中的 X-Frame-Options 响应头提供解决方案。

2. 问题分析与复现

H2 数据库因其具备生产级 SQL 服务器的特性,常用于快速原型开发。但当与 Spring Security 配合使用时,浏览器访问 H2 控制台会被自动限制。

根本原因在于:H2 控制台通过 <iframe> 渲染,而 Spring Security 默认禁用 iframe 以防止点击劫持(clickjacking)等网络攻击

点击劫持攻击中,恶意网站会将目标网站嵌入或覆盖在可点击元素(如框架或按钮)下,诱骗用户与恶意内容交互。安全网站通常会配置防止内容在框架中渲染的策略。

下面通过一个包含 Spring Security 依赖的 Spring Boot 项目来复现这个问题。

2.1. Maven 依赖

首先在 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 负责认证与授权。未自定义用户时,默认生成以下凭据:

  • 用户名:user
  • 密码:控制台输出的随机值

接着添加 H2 数据库依赖:

<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.enabled 默认为 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 数据库控制台登录页

但尝试登录后却得到空白页面:

H2 控制台空白页

问题根源:H2 控制台使用 <iframe> 渲染,而 Spring Security 默认通过 X-Frame-Options 响应头阻止了 iframe 加载。

3. 通过禁用 X-Frame-Options 解决问题

控制台登录后关键组件无法加载,可通过禁用 X-Frame-Options 或仅允许同源框架加载来解决。

3.1. 全局禁用框架保护(开发环境)

如果应用仅用于开发环境,可通过 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();
}

通过 headers() 方法允许框架加载。现在控制台正常显示:

允许框架加载后的 H2 控制台

⚠️ 此方法会全局禁用 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();
}

frameOptions() 配置为仅允许同源应用加载框架,有效降低点击劫持风险。

4. 总结

本文复现了访问 H2 控制台时的空白页问题,并通过配置 Spring Security 的 frameOptions() 解决。我们展示了两种方案:

  • 开发环境:全局禁用 X-Frame-Options
  • 生产环境:仅允许同源框架访问

完整示例代码可在 GitHub 获取。


原始标题:How to Fix H2 Console Not Showing in Browser With Spring Boot | Baeldung