升级JDK21与Spring Boot3.1.4后Keycloak认证接口未调用问题
问题分析与解决方法
核心原因
Spring Boot 3.x(配合JDK21)在静态资源路由优先级、OAuth2集成方式上与Spring Boot 2.x(JDK8)有重大变更,导致请求被静态资源路由优先拦截,而非命中控制器接口。以下是具体解决方案:
1. 调整静态资源路由优先级
Spring Boot 3.x默认将/**路径优先映射到静态资源(如/static/index.html),覆盖了控制器的@RequestMapping规则。解决方式:
- 配置静态资源前缀:在
application.properties或application.yml中指定静态资源的访问前缀,仅让特定路径触发静态资源匹配:# 仅当请求路径以/static/开头时,才匹配静态资源 spring.mvc.static-path-pattern=/static/** # 指定静态资源存放目录(默认是classpath:/static/,可按需调整) spring.web.resources.static-locations=classpath:/static/ - 给控制器路由设置更高优先级:如果不想修改静态资源路径,可给
UserController添加@Order(Ordered.HIGHEST_PRECEDENCE)注解,确保其路由匹配优先于静态资源处理器:@RestController @Order(Ordered.HIGHEST_PRECEDENCE) public class UserController { @GetMapping("/me") public ResponseEntity<?> getCurrentUser() { System.out.println("执行me接口逻辑"); // 业务代码 return ResponseEntity.ok("当前用户信息"); } }
2. 替换Keycloak集成方式(关键变更)
Spring Boot 3.x已废弃旧的keycloak-spring-boot-starter,必须改用官方的OAuth2 Resource Server依赖,否则认证后的请求处理流程会异常:
- 替换依赖:移除旧的Keycloak starter,添加Spring Security OAuth2依赖(以Maven为例):
<!-- 移除旧依赖 --> <!-- <dependency> <groupId>org.keycloak</groupId> <artifactId>keycloak-spring-boot-starter</artifactId> </dependency> --> <!-- 添加新依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-oauth2-resource-server</artifactId> </dependency> - 配置OAuth2 Resource Server:在配置文件中指定Keycloak的JWT issuer地址:
spring.security.oauth2.resourceserver.jwt.issuer-uri=http://your-keycloak-host:8080/realms/your-realm-name - 配置SecurityFilterChain:确保
/me接口允许已认证用户访问:@Configuration @EnableWebSecurity public class SecurityConfig { @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests(auth -> auth .requestMatchers("/static/**", "/").permitAll() .anyRequest().authenticated() ) .oauth2ResourceServer(oauth2 -> oauth2.jwt(Customizer.withDefaults())); return http.build(); } }
3. 排查SPA前端路由转发冲突
如果你的项目是SPA(Vue/React等),之前可能配置了全局转发到index.html的规则,升级后该规则可能覆盖了/me接口:
- 修改转发规则,排除/me路径:
@Configuration public class WebMvcConfig implements WebMvcConfigurer { @Override public void addViewControllers(ViewControllerRegistry registry) { // 仅转发非/api/、非/me的路径到index.html registry.addViewController("/**") .setViewName("forward:/index.html") .setCustomCondition(request -> { String uri = request.getRequestURI(); return !uri.startsWith("/api/") && !uri.equals("/me"); }); } }
4. 基础验证步骤
- 检查启动日志,确认
UserController已被Spring扫描并注册为Bean; - 直接访问
/me路径,查看控制台是否有System.out.println的输出; - 开启Spring Security调试日志(
logging.level.org.springframework.security=DEBUG),确认请求是否通过认证并到达控制器。
内容的提问来源于stack exchange,提问作者Sreejesh
相关产品推荐
相关产品推荐

