fix(deploy): keep PR 576 backport focused

Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
This commit is contained in:
XiaoSeS 2026-08-06 19:05:36 +08:00
parent d0b7a7c5d4
commit 5e3f4e72e7
4 changed files with 14 additions and 42 deletions

View file

@ -1,6 +1,5 @@
package com.iflytek.skillhub.compat;
import com.iflytek.skillhub.auth.oauth.OAuthLoginRedirectSupport;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@ -12,8 +11,14 @@ import java.util.Map;
*/
@RestController
public class WellKnownController {
@GetMapping("/.well-known/clawhub.json")
public Map<String, String> clawhubConfig(HttpServletRequest request) {
return Map.of("apiBase", OAuthLoginRedirectSupport.apiBase(request));
// Honor the deployment sub-path so CLI clients discover /<prefix>/api/v1 instead of
// the domain-root /api/v1. With forward-headers-strategy=framework, an upstream
// X-Forwarded-Prefix is reflected into the request context path.
String contextPath = request.getContextPath();
String prefix = (contextPath == null) ? "" : contextPath;
return Map.of("apiBase", prefix + "/api/v1");
}
}

View file

@ -4,7 +4,6 @@ import com.iflytek.skillhub.auth.oauth.CustomOAuth2UserService;
import com.iflytek.skillhub.auth.oauth.CustomOidcUserService;
import com.iflytek.skillhub.auth.oauth.OAuth2LoginFailureHandler;
import com.iflytek.skillhub.auth.oauth.OAuth2LoginSuccessHandler;
import com.iflytek.skillhub.auth.oauth.OAuthLoginRedirectSupport;
import com.iflytek.skillhub.auth.oauth.SkillHubOAuth2AuthorizationRequestResolver;
import com.iflytek.skillhub.auth.mock.MockAuthFilter;
import com.iflytek.skillhub.auth.policy.RouteSecurityPolicyRegistry;
@ -153,8 +152,12 @@ public class SecurityConfig {
)
.logout(logout -> logout
.logoutUrl("/api/v1/auth/logout")
.logoutSuccessHandler((request, response, authentication) ->
response.sendRedirect(OAuthLoginRedirectSupport.webRoot(request)))
// Redirect to the deployment root honoring any sub-path prefix (X-Forwarded-Prefix
// is reflected into the context path), so logout does not escape a sub-path deployment.
.logoutSuccessHandler((request, response, authentication) -> {
String contextPath = request.getContextPath();
response.sendRedirect(((contextPath == null) ? "" : contextPath) + "/");
})
.invalidateHttpSession(true)
.deleteCookies("SESSION")
)

View file

@ -1,10 +1,7 @@
package com.iflytek.skillhub.auth.oauth;
import jakarta.servlet.http.HttpServletRequest;
/**
* Utility methods and constants for safely handling OAuth redirect targets and
* deployment-path aware browser-visible URLs.
* Utility methods and constants for safely handling post-login redirect targets in OAuth flows.
*/
public final class OAuthLoginRedirectSupport {
@ -14,30 +11,6 @@ public final class OAuthLoginRedirectSupport {
private OAuthLoginRedirectSupport() {
}
public static String apiBase(HttpServletRequest request) {
return deploymentPrefix(request) + "/api/v1";
}
public static String webRoot(HttpServletRequest request) {
return deploymentPrefix(request) + "/";
}
static String deploymentPrefix(HttpServletRequest request) {
if (request == null) {
return "";
}
String rawPrefix = request.getContextPath();
if (rawPrefix == null || rawPrefix.isBlank() || "/".equals(rawPrefix)) {
return "";
}
String prefix = rawPrefix.endsWith("/") ? rawPrefix.substring(0, rawPrefix.length() - 1) : rawPrefix;
if (!prefix.startsWith("/") || prefix.contains("//") || prefix.contains("\\")
|| prefix.contains("?") || prefix.contains("#")) {
return "";
}
return prefix;
}
public static String sanitizeReturnTo(String candidate) {
if (candidate == null || candidate.isBlank()) {
return null;

View file

@ -108,15 +108,6 @@ class OAuth2LoginHandlersTest {
assertThat(response.getRedirectedUrl()).isEqualTo("/skillhub/dashboard/publish");
}
@Test
void deploymentPathSupport_returnsPrefixedApiAndWebRoot() {
MockHttpServletRequest request = new MockHttpServletRequest();
request.setContextPath("/skillhub");
assertThat(OAuthLoginRedirectSupport.apiBase(request)).isEqualTo("/skillhub/api/v1");
assertThat(OAuthLoginRedirectSupport.webRoot(request)).isEqualTo("/skillhub/");
}
/**
* Regression test: when an unauthenticated client hits a protected API endpoint, Spring Security
* caches that request. With {@code SavedRequestAwareAuthenticationSuccessHandler} the post-login