Spring Boot3+Spring Security6集成Keycloak配置问题求助
Spring Boot 3 + Spring Security 6 + Keycloak 配置修正方案
你的配置存在几个关键问题,直接导致了重定向循环、403错误和登出失效:
核心问题分析
- @KeycloakConfiguration 注解冗余冲突:这个注解属于旧版Keycloak专属适配器,Spring Security 6已经通过标准OAuth2/OIDC协议整合Keycloak,保留该注解会干扰正常的OAuth2流程。
- STATELESS 会话策略不兼容:OAuth2授权码模式需要通过会话存储授权请求的临时
state参数(用于防CSRF),设置为STATELESS会导致状态丢失,触发无限制重定向。 - Logout 逻辑完全缺失:空的
logout { }块既不会清理本地会话,也不会调用Keycloak的全局登出端点,导致登出操作无效。 - 静态资源未放行:Thymeleaf应用依赖
/css/**、/js/**等静态资源,你的配置未对这些路径开放权限,可能引发页面加载时的403错误。
修正后的完整配置代码
@Configuration @EnableWebSecurity @EnableMethodSecurity class SecurityConfig { @Value("\${spring.security.oauth2.client.provider.keycloak.issuer-uri}") private lateinit var issuerUri: String @Bean fun configure(http: HttpSecurity): SecurityFilterChain { http .cors { it.disable() } .csrf { // 传统MVC应用建议开启,Thymeleaf会自动处理CSRF令牌 it.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()) } .oauth2Login { oauth2 -> // 自定义登录成功后默认跳转页面,第二个参数设为true强制跳转,忽略原始请求 oauth2.defaultSuccessUrl("/portal/dashboard", true) } .logout { logout -> logout .logoutSuccessUrl("/") .invalidateHttpSession(true) .clearAuthentication(true) // 配置Keycloak全局登出逻辑 .addLogoutHandler(OidcClientInitiatedLogoutSuccessHandler(clientRegistrationRepository())) } .authorizeHttpRequests { authorize -> authorize // 放行首页和静态资源 .requestMatchers("/", "/css/**", "/js/**", "/images/**").permitAll() // 保护portal下的所有路径 .requestMatchers("/portal/**").authenticated() // 其余请求全部放行 .anyRequest().permitAll() } .sessionManagement { session -> // OAuth2授权码流程必须使用STATEFUL会话存储临时状态 session.sessionCreationPolicy(SessionCreationPolicy.STATEFUL) } return http.build() } @Bean fun clientRegistrationRepository(): ClientRegistrationRepository { return InMemoryClientRegistrationRepository(keycloakClientRegistration()) } private fun keycloakClientRegistration(): ClientRegistration { return ClientRegistration.withRegistrationId("keycloak") .clientId("your-client-id") .clientSecret("your-client-secret") .redirectUri("{baseUrl}/login/oauth2/code/keycloak") .authorizationUri("$issuerUri/protocol/openid-connect/auth") .tokenUri("$issuerUri/protocol/openid-connect/token") .userInfoUri("$issuerUri/protocol/openid-connect/userinfo") .userNameAttributeName(IdTokenClaimNames.SUB) .jwkSetUri("$issuerUri/protocol/openid-connect/certs") .clientName("Keycloak") .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE) .scope("openid", "profile", "email") .build() } }
配套配置说明
1. application.yml 基础配置
确保配置文件中填入Keycloak的实例信息:
spring: security: oauth2: client: provider: keycloak: issuer-uri: http://你的Keycloak地址/auth/realms/你的领域名 registration: keycloak: client-id: 你的客户端ID client-secret: 你的客户端密钥 scope: openid,profile,email
2. 依赖调整(移除旧适配器)
使用Spring官方OAuth2依赖替代Keycloak专属适配器,以gradle Kotlin DSL为例:
dependencies { implementation("org.springframework.boot:spring-boot-starter-web") implementation("org.springframework.boot:spring-boot-starter-security") implementation("org.springframework.boot:spring-boot-starter-oauth2-client") implementation("org.springframework.boot:spring-boot-starter-thymeleaf") implementation("org.thymeleaf.extras:thymeleaf-extras-springsecurity6") }
3. Thymeleaf模板权限控制
在页面中通过Spring Security标签判断登录状态:
<div sec:authorize="isAuthenticated()"> <a href="/logout" th:href="@{/logout}">登出</a> </div> <div sec:authorize="!isAuthenticated()"> <a href="/oauth2/authorization/keycloak" th:href="@{/oauth2/authorization/keycloak}">登录</a> </div>
内容的提问来源于stack exchange,提问作者Mateusz
相关产品推荐
相关产品推荐

