OAuth2授权后如何从重定向URI中移除/api上下文路径
移除OAuth2授权重定向URI中的/api上下文路径解决方案
问题分析
你的应用配置了/api上下文路径,Spring Security OAuth2默认会将该路径包含在授权回调URI和授权成功后的重定向地址中,导致前端跳转错误。需要同时调整OAuth2客户端的回调URI配置和授权成功后的重定向逻辑,才能实现动态跳转回去除/api前缀的原页面。
解决方案步骤
1. 调整OAuth2客户端注册的重定向URI
在application.properties中显式指定不带/api前缀的授权回调URI,覆盖Spring Security的默认生成逻辑:
# 新增配置:指定不带/api的回调URI spring.security.oauth2.client.registration.keycloak.redirect-uri=http://localhost:8080/login/oauth2/code/keycloak # 原有配置保持不变 spring.security.oauth2.client.registration.keycloak.client-id=myClientId spring.security.oauth2.client.registration.keycloak.client-secret=myClientSecret spring.security.oauth2.client.provider.keycloak.issuer-uri=http://localhost:8080/realms/master spring.security.oauth2.resourceserver.jwt.issuer-uri=http://localhost:8080/realms/master spring.security.oauth2.client.registration.keycloak.scope=openid spring.security.oauth2.client.registration.keycloak.authorization-grant-type=authorization_code spring.security.oauth2.client.provider.keycloak.user-name-attribute=preferred_username
2. 在Keycloak控制台更新允许的重定向URI
进入Keycloak控制台,找到你的myClientId客户端:
- 切换到Valid Redirect URIs配置项
- 添加
http://localhost:8080/login/oauth2/code/keycloak到允许列表中 - 若仍需要支持带/api的回调,可保留原有
http://localhost:8080/api/login/oauth2/code/keycloak
3. 自定义OAuth2授权成功处理器,动态调整重定向地址
修改Spring Security配置,添加自定义的AuthenticationSuccessHandler,从授权请求中获取原跳转地址并移除/api前缀:
import org.springframework.security.core.Authentication; import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest; import org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestRepository; import org.springframework.security.oauth2.client.web.HttpSessionOAuth2AuthorizationRequestRepository; import org.springframework.security.web.authentication.AuthenticationSuccessHandler; import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.web.SecurityFilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @Configuration @EnableWebSecurity public class SecurityConfig { private final OAuth2AuthorizationRequestRepository<OAuth2AuthorizationRequest> authorizationRequestRepository = new HttpSessionOAuth2AuthorizationRequestRepository(); @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http .csrf().disable() .authorizeHttpRequests(auth -> auth .requestMatchers(matchers).permitAll() .anyRequest().authenticated() ) .httpBasic().disable() .anonymous().disable() .oauth2Login(oauth2 -> oauth2 .authorizationRequestRepository(authorizationRequestRepository) .successHandler(customOAuth2SuccessHandler()) // 绑定自定义成功处理器 ) .logout(logout -> logout .logoutSuccessHandler(oidcLogoutSuccessHandler())) .oauth2ResourceServer(resource -> resource.jwt()); return http.build(); } // 自定义授权成功处理器:移除重定向地址中的/api前缀 private AuthenticationSuccessHandler customOAuth2SuccessHandler() { return (request, response, authentication) -> { OAuth2AuthorizationRequest authRequest = authorizationRequestRepository.loadAuthorizationRequest(request); if (authRequest != null && authRequest.getRedirectUri() != null) { String originalTargetUrl = authRequest.getRedirectUri(); // 替换/api前缀为空,保留后续路径 String adjustedTargetUrl = originalTargetUrl.replaceFirst("^http://localhost:8080/api", "http://localhost:8080"); response.sendRedirect(adjustedTargetUrl); return; } // 兜底跳转至根路径 response.sendRedirect("http://localhost:8080/"); }; } // 保留原有登出处理器实现 private LogoutSuccessHandler oidcLogoutSuccessHandler() { // 你的原有登出逻辑代码 return null; // 替换为实际实现 } }
原理说明
- 显式指定
redirect-uri让OAuth2回调直接指向不带/api的地址,避免Keycloak回调到/api路径 - 自定义成功处理器通过
OAuth2AuthorizationRequestRepository获取用户发起授权前的目标地址,动态去除/api前缀后跳转,实现动态回跳需求
内容的提问来源于stack exchange,提问作者Chshaem
相关产品推荐
相关产品推荐

