Spring Security结合Keycloak:公开页面无跳转校验用户登录态
Spring Security整合Keycloak场景下公开页的已登录状态校验方案
核心目标
实现公开页面在不触发强制登录跳转、不要求用户提前访问受保护资源的前提下,精准识别已在Keycloak完成SSO认证的用户,为页面头部动态渲染专属内容。
具体实现路径
1. 重构Spring Security的路由鉴权规则
- 将所有公开可访问的页面路径配置为
permitAll(),不对该类路径的未认证访问做拦截 - 覆盖Spring Security默认的未认证跳转逻辑:仅当用户访问受保护资源触发鉴权失败时,才重定向到Keycloak的登录流程;访问公开路径时即使未认证,也直接放行,不触发任何跳转
- 配置示例:
@Bean public SecurityFilterChain keycloakSecurityFilterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests(registry -> registry // 公开页面路径完全放行 .requestMatchers("/public/**", "/assets/**").permitAll() // 其余路径走正常Keycloak鉴权 .anyRequest().authenticated() ) .oauth2Login(Customizer.withDefaults()) // 自定义未认证处理逻辑,避免全局强制跳转 .exceptionHandling(handler -> handler .authenticationEntryPoint((request, response, authException) -> { // 公开路径的请求,鉴权失败时直接返回正常响应,不跳转 if (request.getRequestURI().startsWith("/public/")) { response.setStatus(HttpServletResponse.SC_OK); response.setContentType("text/html;charset=utf-8"); return; } // 受保护路径的请求,走原有Keycloak登录跳转逻辑 response.sendRedirect("/oauth2/authorization/keycloak"); }) ); return http.build(); }
2. 搭建轻量的静默状态校验接口
- 专门暴露一个无跳转的状态查询接口,比如路径
/api/public/auth-status,该接口的权限规则为permitAll(),无论用户是否认证都可以访问 - 接口内部直接复用Spring Security的上下文能力校验当前请求的认证状态:
- 从
SecurityContextHolder中读取已解析的认证对象,判断当前请求是否携带有效的Keycloak会话/凭证 - 若凭证有效,直接提取用户基础信息返回给前端,无需触发额外的Keycloak认证流程
- 若凭证无效,直接返回未登录标识,不做任何重定向、token刷新等打断性操作
- 从
- 接口实现示例:
@RestController public class PublicAuthStatusController { @GetMapping("/api/public/auth-status") public Map<String, Object> getLoginStatus() { Authentication auth = SecurityContextHolder.getContext().getAuthentication(); // 匿名状态直接返回未登录标识 if (auth == null || !auth.isAuthenticated() || auth instanceof AnonymousAuthenticationToken) { return Map.of("isLoggedIn", false); } // 已登录状态返回页面头部需要的用户信息 KeycloakPrincipal principal = (KeycloakPrincipal) auth.getPrincipal(); return Map.of( "isLoggedIn", true, "username", principal.getKeycloakSecurityContext().getToken().getPreferredUsername(), "displayName", principal.getKeycloakSecurityContext().getToken().getName() ); } }
3. 前端公开页的适配逻辑
- 页面头部组件挂载完成后,异步发起对
/api/public/auth-status的请求 - 根据接口返回结果动态渲染内容:
- 返回已登录状态时,展示用户专属的头部入口、用户信息等内容
- 返回未登录状态时,展示通用的公开导航栏
- 整个校验过程全程异步,不阻塞页面渲染,也不触发任何页面跳转
常见注意事项
- 配置Keycloak adapter的Cookie作用域时,要保证公开页面所在域名下的后端服务能正常读取Keycloak的SSO会话Cookie,避免出现“明明已在Keycloak登录但校验接口判定未登录”的问题
- 不要在静默校验接口中主动触发token刷新、Keycloak登录弹窗等交互逻辑,如果用户的Keycloak会话已经过期,就直接返回未登录状态,避免打断公开页的浏览体验
- 不要直接拿受保护资源的路径做校验触发器,否则访问受保护路径时会触发默认的登录跳转逻辑,违背“不提前进入登录流程”的要求
内容的提问来源于stack exchange,提问作者Łukasz Bryniarski
相关产品推荐
相关产品推荐

