如何在Spring Security应用中实现SSO自动IDP会话校验?
问题描述
我通过以下代码实现了基于OAuth2和第三方IDP的登录功能:
@EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests(authorizeRequests -> authorizeRequests // .requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll() .antMatchers("/", "/node_modules/**").permitAll() .anyRequest().authenticated()) .oauth2Login() } }
现在我希望应用能在每次请求时校验IDP的会话并实现SSO自动登录,于是尝试了如下配置:
@EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests(authorizeRequests -> authorizeRequests // .requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll() .antMatchers("/", "/node_modules/**").permitAll() .anyRequest().authenticated()) .oauth2Login() .userInfoEndpoint() .userService(oauth2UserService()); } private OAuth2UserService<OAuth2UserRequest, OAuth2User> oauth2UserService() { DefaultOAuth2UserService delegate = new DefaultOAuth2UserService(); return userRequest -> { OAuth2User oAuth2User = delegate.loadUser(userRequest); // You can customize the OAuth2User object here, if needed return oAuth2User; }; } }
预期打开页面时会自动重定向到IDP完成登录,但实际没有任何反应,该如何解决?
解决方案
1. 理解默认行为的限制
你的配置中根路径/被设置为permitAll(),访问该路径时Spring Security不会触发认证流程;同时默认OAuth2登录是被动触发的——只有访问受保护资源时才会跳转到IDP。要实现主动校验IDP会话并自动登录,需要调整配置触发主动SSO检查,同时依赖IDP支持静默登录(通过OpenID Connect的prompt=none参数实现)。
2. 方案一:修改授权规则+配置自动跳转
如果希望访问根路径时也触发SSO校验,可修改授权规则并配置OAuth2自动跳转逻辑:
@EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests(authorizeRequests -> authorizeRequests .antMatchers("/node_modules/**").permitAll() // 根路径也需认证,触发SSO检查 .anyRequest().authenticated()) .oauth2Login(oauth2 -> oauth2 // 登录成功后默认跳转回原路径 .defaultSuccessUrl("/", true) // 添加prompt=none参数,让IDP静默检查会话 .authorizationEndpoint(auth -> auth .authorizationRequestResolver(requestResolver()))); } private OAuth2AuthorizationRequestResolver requestResolver() { DefaultOAuth2AuthorizationRequestResolver resolver = new DefaultOAuth2AuthorizationRequestResolver( clientRegistrationRepository(), "/oauth2/authorization"); resolver.setAuthorizationRequestCustomizer(customizer -> customizer.additionalParameters(params -> params.put("prompt", "none"))); return resolver; } @Autowired private ClientRegistrationRepository clientRegistrationRepository; }
3. 方案二:添加自定义过滤器实现主动校验
如果需要保留根路径的匿名访问,但仍要主动检查IDP会话(用户已在IDP登录时自动登录应用),可添加自定义过滤器:
@EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests(authorizeRequests -> authorizeRequests .antMatchers("/", "/node_modules/**").permitAll() .anyRequest().authenticated()) .oauth2Login() .userInfoEndpoint() .userService(oauth2UserService()) .and() .addFilterBefore(ssoInitiationFilter(), UsernamePasswordAuthenticationFilter.class); } private Filter ssoInitiationFilter() { return new OncePerRequestFilter() { @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { Authentication auth = SecurityContextHolder.getContext().getAuthentication(); // 未认证且非登录回调路径时,触发静默SSO检查 if (auth == null || !(auth instanceof OAuth2AuthenticationToken)) { String requestUri = request.getRequestURI(); if (!requestUri.startsWith("/oauth2/callback") && !requestUri.startsWith("/login")) { // 替换your-idp-registration-id为配置文件中的IDP注册ID response.sendRedirect("/oauth2/authorization/your-idp-registration-id?prompt=none"); return; } } filterChain.doFilter(request, response); } }; } private OAuth2UserService<OAuth2UserRequest, OAuth2User> oauth2UserService() { DefaultOAuth2UserService delegate = new DefaultOAuth2UserService(); return userRequest -> { OAuth2User oAuth2User = delegate.loadUser(userRequest); // 自定义逻辑保留 return oAuth2User; }; } }
4. 关键配置检查
- 确认IDP支持
prompt=none参数(多数OpenID Connect标准IDP都支持),该参数会让IDP静默检查用户会话,无需手动输入账号密码。 - 检查配置文件中的OAuth2客户端信息:
client-id、client-secret、authorization-uri、token-uri、redirect-uri必须与IDP后台配置一致。 - 确保IDP后台已将应用的回调地址加入允许列表,否则会导致认证失败。
内容的提问来源于stack exchange,提问作者BonBonn
相关产品推荐
相关产品推荐

