无法配置permitAll()使/h2-console端点免登录访问
尝试配置端点/h2-console使用permitAll()实现免登录访问,但访问localhost:8080/h2-console时会被重定向到/login页面。
安全配置代码
@Configuration public class SecurityConfig { @Bean public BCryptPasswordEncoder bCryptPasswordEncoder() { return new BCryptPasswordEncoder(); } @Bean public SCryptPasswordEncoder sCryptPasswordEncoder() { return SCryptPasswordEncoder.defaultsForSpringSecurity_v5_8(); } @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .httpBasic().disable() .csrf().disable(); http.authorizeHttpRequests() .requestMatchers("/h2-console/**").permitAll() // .anyRequest().permitAll() < -- 开启此时代码生效,确认项目无其他FilterChain .and() .formLogin() .defaultSuccessUrl("/main", true) .and() .headers().frameOptions().disable(); } }
其他相关配置
AuthenticationConfig
@Configuration public class AuthenticationConfig { @Autowired private CustomAuthProvider authProvider; @Bean public AuthenticationManager authManager(HttpSecurity http) throws Exception { AuthenticationManagerBuilder authenticationManagerBuilder = http.getSharedObject(AuthenticationManagerBuilder.class); authenticationManagerBuilder.authenticationProvider(authProvider); return authenticationManagerBuilder.build(); } }
CustomAuthProvider
@Component public class CustomAuthProvider implements AuthenticationProvider { @Autowired private JpaUserDetailsService userDetailsService; @Autowired private BCryptPasswordEncoder bCryptPasswordEncoder; @Autowired private SCryptPasswordEncoder sCryptPasswordEncoder; @Override public Authentication authenticate(Authentication authentication) throws AuthenticationException { String username = authentication.getName(); String password = authentication.getCredentials().toString(); CustomUserDetails user = userDetailsService.loadUserByUsername(username); switch (user.secureUser().getAlgorithm()) { case BCRYPT: return checkPassword(user, password, bCryptPasswordEncoder); case SCRYPT: return checkPassword(user, password, sCryptPasswordEncoder); default: throw new BadCredentialsException("Bad credentials"); } } private Authentication checkPassword(CustomUserDetails user, String rawPassword, PasswordEncoder encoder) { if (encoder.matches(rawPassword, user.getPassword())) { return new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword(), user.getAuthorities()); } else { throw new BadCredentialsException("Bad credentials"); } } @Override public boolean supports(Class<?> authentication) { return UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication); } }
Spring Security日志
c.e.springinactions.SequrityApplication : Started SequrityApplication in 11.758 seconds (process running for 12.623)
o.s.security.web.FilterChainProxy : Securing GET /h2-console
o.s.s.w.a.AnonymousAuthenticationFilter : Set SecurityContextHolder to anonymous SecurityContext
o.s.s.w.s.HttpSessionRequestCache : Saved request http://localhost:8080/h2-console?continue to session
o.s.s.web.DefaultRedirectStrategy : Redirecting to http://localhost:8080/login
o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet'
你的securityFilterChain方法存在两个核心问题:
- 未返回构建后的HttpSecurity对象:方法末尾必须添加
return http.build();,否则Spring Security不会加载这个配置链。 - 缺少默认请求授权规则:当仅配置
/h2-console/**的permitAll()但未明确其他请求的规则时,Spring Security会默认要求所有请求都需认证,这是导致H2控制台被拦截的关键原因。
修改后的securityFilterChain方法如下:
@Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .httpBasic().disable() .csrf().disable() .authorizeHttpRequests(auth -> auth .requestMatchers("/h2-console/**").permitAll() .anyRequest().authenticated() // 指定除H2控制台外的其他请求需要认证 ) .formLogin(form -> form .defaultSuccessUrl("/main", true) ) .headers(headers -> headers .frameOptions().disable() ); return http.build(); // 必须返回构建完成的配置对象 }
额外检查点:
- 确认
requestMatchers的路径模式/h2-console/**能覆盖控制台的所有子路径请求 - 确保项目中无其他
SecurityFilterChainBean造成配置冲突(你已验证过此点)
修改后重启应用,访问/h2-console即可实现免登录访问。
内容的提问来源于stack exchange,提问作者hhrzc

