fix(auth): project request context under forwarded prefix

Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
This commit is contained in:
XiaoSeS 2026-08-06 16:41:28 +08:00
parent ae36d05fe4
commit e22a3b0ca7
2 changed files with 37 additions and 1 deletions

View file

@ -59,7 +59,7 @@ public class AuthContextFilter extends OncePerRequestFilter {
HttpServletRequest request, HttpServletRequest request,
HttpServletResponse response, HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException { FilterChain filterChain) throws ServletException, IOException {
if (!routeSecurityPolicyRegistry.shouldProjectRequestContext(request.getRequestURI())) { if (!routeSecurityPolicyRegistry.shouldProjectRequestContext(requestPath(request))) {
filterChain.doFilter(request, response); filterChain.doFilter(request, response);
return; return;
} }
@ -88,6 +88,14 @@ public class AuthContextFilter extends OncePerRequestFilter {
filterChain.doFilter(request, response); filterChain.doFilter(request, response);
} }
private String requestPath(HttpServletRequest request) {
String servletPath = request.getServletPath();
if (servletPath != null && !servletPath.isBlank()) {
return servletPath;
}
return request.getRequestURI();
}
private boolean isInactiveUser(String userId) { private boolean isInactiveUser(String userId) {
if (!enforceActiveUserCheck) { if (!enforceActiveUserCheck) {
return false; return false;

View file

@ -120,6 +120,34 @@ class AuthContextFilterTest {
verify(filterChain).doFilter(request, response); verify(filterChain).doFilter(request, response);
} }
@Test
void forwardedPrefixApiRequest_shouldUseServletPathForContextProjection() throws Exception {
PlatformPrincipal principal = new PlatformPrincipal("user-3", "Cara", "cara@example.com", null, "local", Set.of("USER"));
UserAccount user = new UserAccount("user-3", "Cara", "cara@example.com", null);
user.setStatus(UserStatus.ACTIVE);
MockHttpServletRequest request = new MockHttpServletRequest();
request.setContextPath("/skillhub");
request.setRequestURI("/skillhub/api/web/me/namespaces");
request.setServletPath("/api/web/me/namespaces");
request.getSession(true).setAttribute("platformPrincipal", principal);
SecurityContextHolder.getContext().setAuthentication(
new UsernamePasswordAuthenticationToken(principal, null, List.of())
);
MockHttpServletResponse response = new MockHttpServletResponse();
FilterChain filterChain = mock(FilterChain.class);
when(userAccountRepository.findById("user-3")).thenReturn(java.util.Optional.of(user));
when(namespaceMemberRepository.findByUserId("user-3")).thenReturn(List.of());
filter.doFilter(request, response, filterChain);
assertEquals("user-3", request.getAttribute("userId"));
assertTrue(((java.util.Map<Long, NamespaceRole>) request.getAttribute("userNsRoles")).isEmpty());
verify(filterChain).doFilter(request, response);
}
@Test @Test
void anonymousRequest_shouldPassThroughWithoutLoadingUserContext() throws Exception { void anonymousRequest_shouldPassThroughWithoutLoadingUserContext() throws Exception {
MockHttpServletRequest request = new MockHttpServletRequest(); MockHttpServletRequest request = new MockHttpServletRequest();