Reputation: 93
I'm using the H2-Database
and Spring Security
, but I'm unable to open it in the browser at http://localhost:8080/h2-console
Here my pom.xml
(only the H2
entry)
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
Here my application.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
And here is my 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();
}
}
The following is shown in the console if I try to access the console via 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
I have already tried everything I could find on the Internet.
The funny thing is that the "exception handling" works for Swagger
.
If I try to access the database via:
http://localhost:8080/h2-console
I always get the error:
401 - Unauthorized
Each one is strange, because the access was allowed in the 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();
}
I can access the database through an internal database test. This is provided by Intellij
.
However working
/editing
in the database is not possible through this.
AND:
If I change the AUTH_WHITE_LIST
to this, it works.
private static final String[] AUTH_WHITE_LIST = {
"/**"
};
Upvotes: 9
Views: 13612
Reputation: 2566
For Spring Boot version 3+ (Spring Security version 6+) you can use a configuration file with SecurityFilterChain
bean like this code snippet:
import static org.springframework.boot.autoconfigure.security.servlet.PathRequest.toH2Console;
@Configuration
public class ProjectConfig {
@Bean
public SecurityFilterChain chain(HttpSecurity httpSecurity) throws Exception {
httpSecurity
.authorizeHttpRequests(c -> c.requestMatchers(toH2Console()).permitAll())
.csrf(c -> c.ignoringRequestMatchers(toH2Console()).disable())
.headers(h -> h.frameOptions(HeadersConfigurer.FrameOptionsConfig::sameOrigin));
return httpSecurity.build();
}
}
There are four parameters that should be considered:
toH2Console
).authorizeHttpRequests
mehod.ignoringRequestMatchers
method.sameOrigin
method.Upvotes: 1
Reputation: 111
In Spring boot 3, you need to add the following configurations:
first
.csrf(csrf -> csrf
.ignoringRequestMatchers(toH2Console())
.disable())
second
.authorizeHttpRequests(auth -> auth
.requestMatchers(toH2Console()).permitAll())
third
.headers(headers -> headers.frameOptions(FrameOptionsConfig::disable))
Upvotes: 11
Reputation: 115
Step 1: Do import in your SecurityConfig class
import static org.springframework.boot.autoconfigure.security.servlet.PathRequest.toH2Console;
Step 2: Add filter in to context. Pay attention to the lines containing the comment '<-'
@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();
}
}
Upvotes: 2
Reputation: 17
Below is the snippet of my code. I use Spring Boot 3.0.6. It works.
@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();
}
}
Upvotes: 2
Reputation: 21
It is enough to create a new AntPathRequestMatcher within:
.requestMatchers(new AntPathRequestMatcher("/h2-console/**")).permitAll()
To avoid problems of display the frames (X-Frame-Options header will be not added by Spring Security in the response):
http.headers().frameOptions().disable();
Upvotes: 2
Reputation: 139
I've found this article, where the question is well explained: h2-database-console-with-spring-security
Note: The article is not updated to Spring Security 6, due the known deprecation of the WebSecurityConfigurerAdapter class. The code should be updated to:
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();
}
}
Upvotes: 1
Reputation: 3049
You can also explicitly fallback to antMatcher inside requestMatchers
:
import static org.springframework.security.web.util.matcher.AntPathRequestMatcher.antMatcher;
....
.....
return http
.authorizeHttpRequests()
.requestMatchers(antMatcher("/h2-console/**")).permitAll()
.anyRequest().authenticated()
.and()
.build();
Upvotes: 4
Reputation: 61
According to the post on spring blog about Spring Security without the WebSecurityConfigurerAdapter we can use WebSecurityCustomize for ignoring the whole endpoint from the security. The case fits perfectly to publish the h2 console, because we want to ignore only this particular endpoint in the case of security. The working example:
@Bean
public WebSecurityCustomizer webSecurityCustomizer() {
return (web) -> web.ignoring().requestMatchers(new AntPathRequestMatcher(H2_CONSOLE_PATH));
}
And that's all what we need, probably the cleanest solution to this problem.
Upvotes: 6
Reputation: 13289
I could reproduce with spring-boot:3.0.0(web, security, h2, ...) and:
return http
.authorizeHttpRequests()
.requestMatchers("/h2-console/**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.and()
.csrf().ignoringRequestMatchers("/h2-console/**")
.and()
.headers().frameOptions().sameOrigin()
.and()
.build();
(/h2-console
is still protected!)
(spring-boot-way):
import static //
org.springframework.boot.autoconfigure.security.servlet.PathRequest.toH2Console; // !
...
.requestMatchers(toH2Console()).permitAll()
...
.csrf().ignoringRequestMatchers(toH2Console())
Refs:
It uses internally:
new AntPathRequestMatcher(h2ConsoleProperties.get().getPath() + "/**");
which seems to be different/better than the requestMatcher(String... paths)
(AbstractRequestMatcherRegistry
), which invokes this (with 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])); }
... alternatives:
RequestMatchers.antMatcher(null, pathToH2+"/**")
.AntPathRequestMatcher
(for ignore case (and all http methods), prefer constructors to factories;)MvcMatcher
I would not do it (unsecured) in production!
Upvotes: 24