Skip to content

Document how to access the H2 Console in a secured web application #29932

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 4 commits into from
Closed

Document how to access the H2 Console in a secured web application #29932

wants to merge 4 commits into from

Conversation

hpoettker
Copy link
Contributor

Resolves #28268.

The WebSecurityCustomizer is a bit blunt. But for a development setup, a proper SecurityFilterChain seems overly ceremonial, in my opinion. 😄

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Feb 22, 2022
Copy link
Member

@snicoll snicoll left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR. I've added a couple comments that are more directed to the team as I'd like to get more feedback on this. I've flagged the issue accordingly.

==== Configuring Spring Security for H2 Console
H2 Console uses frames and, as it's intended for development only, does not implement CSRF protection measures. If your application uses Spring Security, you need to configure it accordingly.

For example, Spring Security will ignore the console if the following `WebSecurityCustomizer` is exposed:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need to be more explicit than "ignoring" and mention anybody could access it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree. In the context of CSRF, it would be better to just disable Security's protection rather than ignoring entirely. This is what the old (1.x) auto-configuration for the console used to do:

@Override
public void configure(HttpSecurity http) throws Exception {
String path = this.console.getPath();
String antPattern = (path.endsWith("/") ? path + "**" : path + "/**");
HttpSecurity h2Console = http.antMatcher(antPattern);
h2Console.csrf().disable();
h2Console.httpBasic();
h2Console.headers().frameOptions().sameOrigin();
String[] roles = this.security.getUser().getRole().toArray(new String[0]);
SecurityAuthorizeMode mode = this.security.getBasic().getAuthorizeMode();
if (mode == null || mode == SecurityAuthorizeMode.ROLE) {
http.authorizeRequests().anyRequest().hasAnyRole(roles);
}
else if (mode == SecurityAuthorizeMode.AUTHENTICATED) {
http.authorizeRequests().anyRequest().authenticated();
}
}

@snicoll snicoll added the for: team-attention An issue we'd like other members of the team to review label Feb 22, 2022
@hpoettker
Copy link
Contributor Author

@snicoll @wilkinsona Thanks for the feedback!

I'll rewrite the PR to show how a dedicated SecurityFilterChain can be exposed for the console.

@hpoettker hpoettker marked this pull request as draft February 28, 2022 10:39
@wilkinsona
Copy link
Member

I'm not sure that we should go that far. The security for the console may need to be quite complex, and that'll depend on the user's security configuration which is an unknown to us. I think we should avoid prescribing a particular approach and just point out any common pitfalls such as the situation with CSRF protection.

@hpoettker
Copy link
Contributor Author

I removed the code snippet and added some explanations on what needs to be done together with a warning not to do it in production.

@hpoettker hpoettker marked this pull request as ready for review February 28, 2022 23:44
@wilkinsona
Copy link
Member

@hpoettker Your code snippet in 1573e32 has changed my mind. I was concerned about providing something that users would copy and paste and try to use as-is. I think your snippet is informative without making that too much of a risk. Sorry to be a pain, but would you mind reinstating it?

@wilkinsona wilkinsona added status: waiting-for-feedback We need additional information before we can continue type: documentation A documentation update and removed status: waiting-for-feedback We need additional information before we can continue for: team-attention An issue we'd like other members of the team to review status: waiting-for-triage An issue we've not yet triaged labels Mar 3, 2022
@wilkinsona wilkinsona added this to the 2.5.x milestone Mar 3, 2022
@hpoettker
Copy link
Contributor Author

hpoettker commented Mar 3, 2022

@wilkinsona I reverted the last commit. Quick thing and no pain at all. 😄

I fully agree that one needs to be careful with publishing code snippets in the reference documentation that have the potential to create security risks if used lightheartedly. The code snippet makes it pretty clear that it is not supposed to be used in production code. However, if just the bean method is copied verbatim and the comment asking for authorization to be configured is ignored, then the H2 console is again unprotected as in the first draft with the WebSecurityCustomizer. I realized that only after pushing, and then wrote the version without any code snippet.

@hpoettker
Copy link
Contributor Author

The code snippet that I came up with that is the most safe to be copied and pasted is

@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class H2ConsoleFilterBean extends HeaderWriterFilter {

  private final RequestMatcher h2ConsoleRequestMatcher = PathRequest.toH2Console();

  public H2ConsoleFilterBean() {
    super(Arrays.asList(new XFrameOptionsHeaderWriter(XFrameOptionsMode.SAMEORIGIN)));
  }

  @Override
  protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
      throws ServletException, IOException {
    CsrfFilter.skipRequest(request);
    super.doFilterInternal(request, response, filterChain);
  }

  @Override
  protected boolean shouldNotFilter(HttpServletRequest request) {
    return !h2ConsoleRequestMatcher.matches(request);
  }

}

But this code snippet is quite dense and may confuse more people than it helps.

@snicoll snicoll self-assigned this Mar 21, 2022
snicoll pushed a commit that referenced this pull request Mar 21, 2022
@snicoll snicoll closed this in 0c90330 Mar 21, 2022
@snicoll snicoll modified the milestones: 2.5.x, 2.5.11 Mar 21, 2022
@snicoll snicoll changed the title Document WebSecurityCustomizer for H2 Console Document how to access the H2 Console in a secured web application Mar 21, 2022
@linghengqian
Copy link

@hpoettker

  • It seems that Spring Security encourages the adoption of the Lambda DSL instead of and(), in your opinion, would the following be better?
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
SecurityFilterChain h2ConsoleSecurityFilterChain(HttpSecurity http) throws Exception {
    return http.requestMatcher(PathRequest.toH2Console())
            .csrf(AbstractHttpConfigurer::disable)
            .headers(headers -> headers.frameOptions(HeadersConfigurer.FrameOptionsConfig::sameOrigin))
            .build();
}

@hpoettker
Copy link
Contributor Author

Hi @linghengqian, thanks for joining the discussion!
Please note that your question could be perceived as off-topic here and that I won't answer it. As an unaffiliated contributor, I really have no authority to do so.

@wilkinsona
Copy link
Member

The Spring Security docs seem to use the lambda-style API, such as in their example for disabling CSRF. I think it makes sense to align with that. I've opened #30432.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: documentation A documentation update
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants