Spring Boot应用配置AzureAD OAuth2与/rest/api/**路径Basic认证问题
问题根因
Spring Security 多配置类按照@Order注解的数值从小到大匹配优先级,且每个配置类默认处理所有请求,一旦请求匹配上优先级更高的配置规则,就不会再进入后续低优先级配置执行逻辑。
你现有配置的问题:
- 优先级更高的
WebSecurityAzureConfig处理全量请求,你要么把/rest/api/**设为permitAll直接放行,要么删除该行后要求该路径走OAuth2认证,始终轮不到优先级更低的Basic认证配置生效。
可行修改方案
核心调整点
- 调整两个配置类的优先级:将处理
/rest/api/**的Basic认证配置优先级调到最高(@Order(1)),Azure OAuth2配置调整为次优先级(@Order(2)) - 给Basic认证配置添加路径限定,仅处理
/rest/api/**开头的请求,其余请求自动跳过该配置,走后续OAuth2认证逻辑 - 删除Azure OAuth2配置中
/rest/api/**的permitAll规则 - 补充Basic认证的用户校验逻辑(示例提供内存用户配置,可根据业务需求替换为数据库查询实现)
修改后完整配置代码
package com.test.security; import com.azure.spring.aad.webapp.AADWebSecurityConfigurerAdapter; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.annotation.Order; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.crypto.password.NoOpPasswordEncoder; import org.springframework.security.provisioning.InMemoryUserDetailsManager; @Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true) public class WebSecurityConfig { @Autowired private AzureAuthenticationSuccessHandler authenticationSuccessHandler; @Autowired private AzureOidcUserService oidcUserService; @SuppressWarnings("deprecation") @Bean public NoOpPasswordEncoder passwordEncoder() { return (NoOpPasswordEncoder) NoOpPasswordEncoder.getInstance(); } // Basic认证配置,优先级最高,仅处理/rest/api/**路径 @Configuration @Order(1) public class WebSecurityBasicConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { // 限定该配置仅处理/rest/api/**路径的请求 http.antMatcher("/rest/api/**") .authorizeRequests() .anyRequest().authenticated() .and() .httpBasic() .and() // API接口一般无状态,禁用CSRF和session .csrf().disable() .sessionManagement().disable(); } // 示例:内存存储Basic认证的用户名密码,可替换为自定义UserDetailsService对接数据库查询 @Bean @Override public UserDetailsService userDetailsService() { UserDetails user = User.withUsername("apiUser") .password("apiPassword") .roles("API_USER") .build(); return new InMemoryUserDetailsManager(user); } } // Azure AD OAuth2认证配置,次优先级,处理除/rest/api/**外的所有剩余请求 @Configuration @Order(2) public class WebSecurityAzureConfig extends AADWebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { super.configure(http); http.headers().frameOptions().sameOrigin() .and() .csrf().disable() .authorizeRequests() .antMatchers("/css/**").permitAll() .antMatchers("/fonts/**").permitAll() .antMatchers("/images/**").permitAll() .antMatchers("/scripts/**").permitAll() .antMatchers("/swagger-resources/**", "/swagger-ui.html", "/webjars/**", "/v2/api-docs", "/csrf").permitAll() .antMatchers("/version").permitAll() .antMatchers("/healthCheck").permitAll() .antMatchers("/h2-console/**").permitAll() .antMatchers("/", "/login", "/oauth/**").permitAll() .anyRequest().authenticated() .and() .formLogin() .loginPage("/login") .and() .oauth2Login() .userInfoEndpoint() .oidcUserService(oidcUserService) .and() .successHandler(authenticationSuccessHandler) .and() .logout() .invalidateHttpSession(true) .clearAuthentication(true) .logoutSuccessUrl("/logoutSuccess") .permitAll(); } } }
注意事项
示例中使用的NoOpPasswordEncoder为明文密码编码器,仅适合测试使用,生产环境建议替换为BCryptPasswordEncoder等加密编码器。
内容的提问来源于stack exchange,提问作者Patrick C.
相关产品推荐
相关产品推荐

