1
0
mirror of synced 2026-08-05 17:57:15 +00:00

Add setFavorRelativeUris

This places the new functionality behind a setting so that
we can remain passive until we can change the setting in
the next major release.

Issue gh-7273
This commit is contained in:
Josh Cummings
2024-12-17 17:12:41 -07:00
parent 7848b959da
commit 3eeb4317f6
25 changed files with 288 additions and 98 deletions
@@ -78,6 +78,8 @@ public class LoginUrlAuthenticationEntryPoint implements AuthenticationEntryPoin
private boolean useForward = false;
private boolean favorRelativeUris = false;
private final RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
/**
@@ -144,23 +146,41 @@ public class LoginUrlAuthenticationEntryPoint implements AuthenticationEntryPoin
protected String buildRedirectUrlToLoginPage(HttpServletRequest request, HttpServletResponse response,
AuthenticationException authException) {
String loginForm = determineUrlToUseForThisRequest(request, response, authException);
if (UrlUtils.isAbsoluteUrl(loginForm) || !this.forceHttps || "https".equals(request.getScheme())) {
if (UrlUtils.isAbsoluteUrl(loginForm)) {
return loginForm;
}
if (requiresRewrite(request)) {
return httpsUri(request, loginForm);
}
return this.favorRelativeUris ? loginForm : absoluteUri(request, loginForm).getUrl();
}
private boolean requiresRewrite(HttpServletRequest request) {
return this.forceHttps && "http".equals(request.getScheme());
}
private String httpsUri(HttpServletRequest request, String path) {
int serverPort = this.portResolver.getServerPort(request);
Integer httpsPort = this.portMapper.lookupHttpsPort(serverPort);
if (httpsPort == null) {
logger.warn(LogMessage.format("Unable to redirect to HTTPS as no port mapping found for HTTP port %s",
serverPort));
return loginForm;
return this.favorRelativeUris ? path : absoluteUri(request, path).getUrl();
}
RedirectUrlBuilder builder = absoluteUri(request, path);
builder.setScheme("https");
builder.setPort(httpsPort);
return builder.getUrl();
}
private RedirectUrlBuilder absoluteUri(HttpServletRequest request, String path) {
RedirectUrlBuilder urlBuilder = new RedirectUrlBuilder();
urlBuilder.setScheme("https");
urlBuilder.setScheme(request.getScheme());
urlBuilder.setServerName(request.getServerName());
urlBuilder.setPort(httpsPort);
urlBuilder.setPort(this.portResolver.getServerPort(request));
urlBuilder.setContextPath(request.getContextPath());
urlBuilder.setPathInfo(loginForm);
return urlBuilder.getUrl();
urlBuilder.setPathInfo(path);
return urlBuilder;
}
/**
@@ -238,4 +258,18 @@ public class LoginUrlAuthenticationEntryPoint implements AuthenticationEntryPoin
return this.useForward;
}
/**
* Favor using relative URIs when formulating a redirect.
*
* <p>
* Note that a relative redirect is not always possible. For example, when redirecting
* from {@code http} to {@code https}, the URL needs to be absolute.
* </p>
* @param favorRelativeUris whether to favor relative URIs or not
* @since 6.5
*/
public void setFavorRelativeUris(boolean favorRelativeUris) {
this.favorRelativeUris = favorRelativeUris;
}
}
@@ -129,18 +129,18 @@ public class LoginUrlAuthenticationEntryPointTests {
ep.setPortResolver(new MockPortResolver(80, 443));
ep.afterPropertiesSet();
ep.commence(request, response, null);
assertThat(response.getRedirectedUrl()).isEqualTo("/bigWebApp/hello");
assertThat(response.getRedirectedUrl()).isEqualTo("https://www.example.com/bigWebApp/hello");
request.setServerPort(8443);
response = new MockHttpServletResponse();
ep.setPortResolver(new MockPortResolver(8080, 8443));
ep.commence(request, response, null);
assertThat(response.getRedirectedUrl()).isEqualTo("/bigWebApp/hello");
assertThat(response.getRedirectedUrl()).isEqualTo("https://www.example.com:8443/bigWebApp/hello");
// access to https via http port
request.setServerPort(8080);
response = new MockHttpServletResponse();
ep.setPortResolver(new MockPortResolver(8080, 8443));
ep.commence(request, response, null);
assertThat(response.getRedirectedUrl()).isEqualTo("/bigWebApp/hello");
assertThat(response.getRedirectedUrl()).isEqualTo("https://www.example.com:8443/bigWebApp/hello");
}
@Test
@@ -158,7 +158,7 @@ public class LoginUrlAuthenticationEntryPointTests {
request.setServerPort(80);
MockHttpServletResponse response = new MockHttpServletResponse();
ep.commence(request, response, null);
assertThat(response.getRedirectedUrl()).isEqualTo("/bigWebApp/hello");
assertThat(response.getRedirectedUrl()).isEqualTo("http://localhost/bigWebApp/hello");
}
@Test
@@ -178,7 +178,7 @@ public class LoginUrlAuthenticationEntryPointTests {
ep.commence(request, response, null);
// Response doesn't switch to HTTPS, as we didn't know HTTP port 8888 to HTTP port
// mapping
assertThat(response.getRedirectedUrl()).isEqualTo("/bigWebApp/hello");
assertThat(response.getRedirectedUrl()).isEqualTo("http://localhost:8888/bigWebApp/hello");
}
@Test
@@ -237,4 +237,54 @@ public class LoginUrlAuthenticationEntryPointTests {
assertThatIllegalArgumentException().isThrownBy(ep::afterPropertiesSet);
}
@Test
public void commenceWhenFavorRelativeUrisThenHttpsSchemeNotIncluded() throws Exception {
MockHttpServletRequest request = new MockHttpServletRequest();
request.setRequestURI("/some_path");
request.setScheme("https");
request.setServerName("www.example.com");
request.setContextPath("/bigWebApp");
request.setServerPort(443);
MockHttpServletResponse response = new MockHttpServletResponse();
LoginUrlAuthenticationEntryPoint ep = new LoginUrlAuthenticationEntryPoint("/hello");
ep.setFavorRelativeUris(true);
ep.setPortMapper(new PortMapperImpl());
ep.setForceHttps(true);
ep.setPortMapper(new PortMapperImpl());
ep.setPortResolver(new MockPortResolver(80, 443));
ep.afterPropertiesSet();
ep.commence(request, response, null);
assertThat(response.getRedirectedUrl()).isEqualTo("/bigWebApp/hello");
request.setServerPort(8443);
response = new MockHttpServletResponse();
ep.setPortResolver(new MockPortResolver(8080, 8443));
ep.commence(request, response, null);
assertThat(response.getRedirectedUrl()).isEqualTo("/bigWebApp/hello");
// access to https via http port
request.setServerPort(8080);
response = new MockHttpServletResponse();
ep.setPortResolver(new MockPortResolver(8080, 8443));
ep.commence(request, response, null);
assertThat(response.getRedirectedUrl()).isEqualTo("/bigWebApp/hello");
}
@Test
public void commenceWhenFavorRelativeUrisThenHttpSchemeNotIncluded() throws Exception {
LoginUrlAuthenticationEntryPoint ep = new LoginUrlAuthenticationEntryPoint("/hello");
ep.setFavorRelativeUris(true);
ep.setPortMapper(new PortMapperImpl());
ep.setPortResolver(new MockPortResolver(80, 443));
ep.afterPropertiesSet();
MockHttpServletRequest request = new MockHttpServletRequest();
request.setRequestURI("/some_path");
request.setContextPath("/bigWebApp");
request.setScheme("http");
request.setServerName("localhost");
request.setContextPath("/bigWebApp");
request.setServerPort(80);
MockHttpServletResponse response = new MockHttpServletResponse();
ep.commence(request, response, null);
assertThat(response.getRedirectedUrl()).isEqualTo("/bigWebApp/hello");
}
}