h2 -数据库控制台没有打开Spring-Security



我正在使用H2-DatabaseSpring Security,但我无法在浏览器中打开http://localhost:8080/h2-console

这里是我的pom.xml(只有H2条目)

<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>

Here myapplication.properties

spring.datasource.url=jdbc:h2:file:/data/noNameDB
spring.h2.console.enabled=true
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=admin
spring.datasource.password=admin
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.h2.console.path=/h2-console
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update
spring.jackson.serialization.fail-on-empty-beans=false

这里是SecurityConfig.java

import com.example.noName.security.JwtAuthenticationEntryPoint;
import com.example.noName.security.JwtAuthenticationFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@Configuration
@EnableWebSecurity
public class SecurityConfig {

private static final String[] AUTH_WHITE_LIST = {
"/v3/api-docs/**",
"/swagger-ui/**",
"/v2/api-docs/**",
"/swagger-resources/**",
"/h2-console/**",
"/console/**",
"/account/**"
};
@Autowired
private JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
@Bean
public JwtAuthenticationFilter jwtAuthenticationFilter() {
return new JwtAuthenticationFilter();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}

@Bean
public AuthenticationManager authenticationManager(
AuthenticationConfiguration authConfig) throws Exception {
return authConfig.getAuthenticationManager();
}

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.cors()
.and()
.csrf()
.disable()
.exceptionHandling()
.authenticationEntryPoint(jwtAuthenticationEntryPoint)
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeHttpRequests()
.requestMatchers(AUTH_WHITE_LIST)
.permitAll()
.and()
.headers()
.frameOptions()
.disable()
.and()
.authorizeHttpRequests()
.anyRequest()
.authenticated()
.and()
.httpBasic()
.and()
.addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
.httpBasic();
return http.build();
}
}

如果我尝试通过http://localhost:8080/h2-console

访问控制台,控制台将显示以下内容
INFO 3664 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet 'dispatcherServlet'
INFO 3664 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
INFO 3664 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 1 ms

我已经尝试了所有我能在网上找到的。

有趣的是异常处理"适用于Swagger。如果我试图通过以下方式访问数据库:

http://localhost:8080/h2-console

我总是得到错误:

401 - Unauthorized

每一个都是奇怪的,因为SecurityConfig允许访问。

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.cors()
.and()
.csrf()
.disable()
.exceptionHandling()
.authenticationEntryPoint(jwtAuthenticationEntryPoint)
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeHttpRequests()
.requestMatchers(AUTH_WHITE_LIST)
.permitAll()
.and()
.headers()
.frameOptions()
.disable()
.and()
.authorizeHttpRequests()
.anyRequest()
.authenticated()
.and()
.httpBasic()
.and()
.addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
.httpBasic();
return http.build();
}

我可以通过内部数据库测试访问数据库。这由Intellij提供。

然而,working/editing在数据库中是不可能通过这个。

:

如果我改变AUTH_WHITE_LIST为这个,它工作。

private static final String[] AUTH_WHITE_LIST = {
"/**"
};

我可以复制spring-boot:3.0.0(web, security, h2,…)和:

return http
.authorizeHttpRequests()
.requestMatchers("/h2-console/**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.and()
.csrf().ignoringRequestMatchers("/h2-console/**")
.and()
.headers().frameOptions().sameOrigin()
.and()
.build();

(/h2-console仍受保护!)

修复:

(spring-boot-way):

import static //
org.springframework.boot.autoconfigure.security.servlet.PathRequest.toH2Console; // !
...
.requestMatchers(toH2Console()).permitAll()
...
.csrf().ignoringRequestMatchers(toH2Console())

参:

  • https://jessitron.com/2020/06/15/spring-security-for-h2-console/
  • PathRequest

内部使用:

new AntPathRequestMatcher(h2ConsoleProperties.get().getPath() + "/**");

似乎与requestMatcher(String... paths)(AbstractRequestMatcherRegistry)不同/更好,它调用了这个(与method==null一起):

public C requestMatchers(HttpMethod method, String... patterns) {
List<RequestMatcher> matchers = new ArrayList<>();
if (mvcPresent) {
matchers.addAll(createMvcMatchers(method, patterns)); // <- we land here obviously
} else {
matchers.addAll(RequestMatchers.antMatchers(method, patterns));     
}
return requestMatchers(matchers.toArray(new RequestMatcher[0]));
}

…替代品:

  • RequestMatchers.antMatcher(null, pathToH2+"/**").
  • AntPathRequestMatcher(对于忽略大小写(和所有http方法),更喜欢构造函数而不是工厂;)
  • MvcMatcher(对于h2-console是不可能的,因为它不是mvc;

但/

我会在生产中不这样做(不安全)!

根据spring博客上关于不使用WebSecurityConfigurerAdapter的spring安全性的文章,我们可以使用WebSecurityCustomize从安全性中忽略整个端点。这种情况非常适合发布h2控制台,因为在安全性的情况下,我们只想忽略这个特定的端点。工作示例:

@Bean
public WebSecurityCustomizer webSecurityCustomizer() {
return (web) -> web.ignoring().requestMatchers(new AntPathRequestMatcher(H2_CONSOLE_PATH));
}

这就是我们所需要的,可能是这个问题最干净的解决方案。

你也可以显式回退到requestMatchers:

中的antMatcher:
import static org.springframework.security.web.util.matcher.AntPathRequestMatcher.antMatcher;
....
.....
return http
.authorizeHttpRequests()
.requestMatchers(antMatcher("/h2-console/**")).permitAll()
.anyRequest().authenticated()
.and()
.build();

在Spring boot 3中,您需要添加以下配置:

首先

.csrf(csrf -> csrf
.ignoringRequestMatchers(toH2Console())
.disable())

第二

.authorizeHttpRequests(auth -> auth
.requestMatchers(toH2Console()).permitAll())

第三
.headers(headers -> headers.frameOptions(FrameOptionsConfig::disable))

我找到了这篇文章,其中很好地解释了这个问题:h2-database-console-with-spring-security

注意:由于WebSecurityConfigurerAdapter类的已知弃用,本文没有更新到Spring Security 6。代码应该更新为:

package com.myapp.configuration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;
import static org.springframework.boot.autoconfigure.security.servlet.PathRequest.toH2Console;  
@Configuration
public class CustomSecurityConfiguration{

@Bean
SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
http.authorizeHttpRequests()
.requestMatchers("/").permitAll()
.requestMatchers(toH2Console()).permitAll()
.and().csrf().ignoringRequestMatchers(toH2Console())
.and().formLogin()
.and().httpBasic();

// Use them only in development or demo environments. NEVER in production !!!
// http.csrf().disable();
http.headers().frameOptions().disable();

return http.build();
}
}

创建一个新的AntPathRequestMatcher就足够了:

.requestMatchers(new AntPathRequestMatcher("/h2-console/**")).permitAll()

为了避免显示帧的问题(X-Frame-Options头将不会被Spring Security添加到响应中):

http.headers().frameOptions().disable();

下面是我的代码片段。我使用Spring Boot 3.0.6。它的工作原理。

@Configuration
public class SecurityConfiguration {
@Bean
SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
http.authorizeHttpRequests().requestMatchers(antMatcher("/h2-console/**")).permitAll()
.and().csrf().ignoringRequestMatchers(antMatcher("/h2-console/**"))
.and().headers().frameOptions().disable();
return http.build();
}
}

步骤1:不要在SecurityConfig类中导入

import static org.springframework.boot.autoconfigure.security.servlet.PathRequest.toH2Console;

步骤2:在上下文中添加过滤器。注意包含注释'<-'

的行。
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception 
{
http
.authorizeHttpRequests((requests) -> requests
// another matchers
.requestMatchers(toH2Console()).permitAll() // <-
// another matchers
.anyRequest().authenticated()
)
.formLogin((login) -> login
.loginPage("/login")
.permitAll()
)
.logout((logout) -> logout
.permitAll()
)
.csrf((protection) -> protection
.ignoringRequestMatchers(toH2Console()) // <- 
)
.headers((header) -> header
.frameOptions().sameOrigin()
);
return http.build();
}
}

最新更新