Skip to content

Commit e18dda7

Browse files
committed
DefaultRedirectStrategy Host-less Redirect
Fixes gh-7273
1 parent 26a6524 commit e18dda7

File tree

2 files changed

+62
-12
lines changed

2 files changed

+62
-12
lines changed

web/src/main/java/org/springframework/security/web/DefaultRedirectStrategy.java

+29-10
Original file line numberDiff line numberDiff line change
@@ -16,26 +16,30 @@
1616
package org.springframework.security.web;
1717

1818
import java.io.IOException;
19-
2019
import javax.servlet.http.HttpServletRequest;
2120
import javax.servlet.http.HttpServletResponse;
2221

2322
import org.apache.commons.logging.Log;
2423
import org.apache.commons.logging.LogFactory;
24+
2525
import org.springframework.security.web.util.UrlUtils;
26+
import org.springframework.web.util.UriComponents;
27+
import org.springframework.web.util.UriComponentsBuilder;
2628

2729
/**
2830
* Simple implementation of <tt>RedirectStrategy</tt> which is the default used throughout
2931
* the framework.
3032
*
3133
* @author Luke Taylor
34+
* @author Josh Cummings
3235
* @since 3.0
3336
*/
3437
public class DefaultRedirectStrategy implements RedirectStrategy {
3538

3639
protected final Log logger = LogFactory.getLog(getClass());
3740

3841
private boolean contextRelative;
42+
private boolean hostRelative = true;
3943

4044
/**
4145
* Redirects the response to the supplied URL.
@@ -68,25 +72,40 @@ protected String calculateRedirectUrl(String contextPath, String url) {
6872
}
6973

7074
// Full URL, including http(s)://
75+
boolean hostRelative = this.hostRelative;
76+
boolean contextRelative = isContextRelative();
7177

72-
if (!isContextRelative()) {
78+
if (!hostRelative && !contextRelative) {
7379
return url;
7480
}
7581

76-
// Calculate the relative URL from the fully qualified URL, minus the last
77-
// occurrence of the scheme and base context.
78-
url = url.substring(url.lastIndexOf("://") + 3); // strip off scheme
79-
url = url.substring(url.indexOf(contextPath) + contextPath.length());
82+
UriComponents components = UriComponentsBuilder
83+
.fromHttpUrl(url).build();
8084

81-
if (url.length() > 1 && url.charAt(0) == '/') {
82-
url = url.substring(1);
85+
String path = components.getPath();
86+
if (contextRelative) {
87+
path = path.substring(path.indexOf(contextPath) + contextPath.length());
88+
if (path.length() > 1 && path.charAt(0) == '/') {
89+
path = path.substring(1);
90+
}
8391
}
8492

85-
return url;
93+
return UriComponentsBuilder
94+
.fromPath(path)
95+
.query(components.getQuery())
96+
.build().toString();
97+
}
98+
99+
/**
100+
* If <tt>true</tt>, causes any redirection URLs to be calculated minus the authority
101+
* (defaults to <tt>true</tt>).
102+
*/
103+
public void setHostRelative(boolean hostRelative) {
104+
this.hostRelative = hostRelative;
86105
}
87106

88107
/**
89-
* If <tt>true</tt>, causes any redirection URLs to be calculated minus the protocol
108+
* If <tt>true</tt>, causes any redirection URLs to be calculated minus the authority
90109
* and context path (defaults to <tt>false</tt>).
91110
*/
92111
public void setContextRelative(boolean useRelativeContext) {

web/src/test/java/org/springframework/security/web/DefaultRedirectStrategyTests.java

+33-2
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,13 @@
1515
*/
1616
package org.springframework.security.web;
1717

18-
import static org.assertj.core.api.Assertions.*;
19-
2018
import org.junit.Test;
19+
2120
import org.springframework.mock.web.MockHttpServletRequest;
2221
import org.springframework.mock.web.MockHttpServletResponse;
2322

23+
import static org.assertj.core.api.Assertions.assertThat;
24+
2425
/**
2526
*
2627
* @author Luke Taylor
@@ -56,4 +57,34 @@ public void contextRelativeUrlWithMultipleSchemesInHostnameIsHandledCorrectly()
5657

5758
assertThat(response.getRedirectedUrl()).isEqualTo("remainder");
5859
}
60+
61+
// gh-7273
62+
@Test
63+
public void sendRedirectWhenUsingDefaultsThenRemovesHost()
64+
throws Exception {
65+
DefaultRedirectStrategy rds = new DefaultRedirectStrategy();
66+
MockHttpServletRequest request = new MockHttpServletRequest();
67+
request.setContextPath("/context");
68+
MockHttpServletResponse response = new MockHttpServletResponse();
69+
70+
rds.sendRedirect(request, response,
71+
"https://context.blah.com/context/remainder");
72+
assertThat(response.getRedirectedUrl()).isEqualTo("/context/remainder");
73+
}
74+
75+
// gh-7273
76+
@Test
77+
public void sendRedirectWhenHostRelativeFalseThenKeepsHost()
78+
throws Exception {
79+
DefaultRedirectStrategy rds = new DefaultRedirectStrategy();
80+
rds.setHostRelative(false);
81+
MockHttpServletRequest request = new MockHttpServletRequest();
82+
request.setContextPath("/context");
83+
MockHttpServletResponse response = new MockHttpServletResponse();
84+
85+
rds.sendRedirect(request, response,
86+
"https://context.blah.com/context/remainder");
87+
88+
assertThat(response.getRedirectedUrl()).isEqualTo("https://context.blah.com/context/remainder");
89+
}
5990
}

0 commit comments

Comments
 (0)