Merge branch '3.2.x'

Closes gh-40501
This commit is contained in:
Moritz Halbritter 2024-04-24 16:06:07 +02:00
commit 2c346bcdcb
2 changed files with 40 additions and 5 deletions

View File

@ -77,6 +77,7 @@ import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.StatisticsHandler;
import org.eclipse.jetty.session.DefaultSessionCache;
import org.eclipse.jetty.session.FileSessionDataStore;
import org.eclipse.jetty.session.SessionConfig;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.resource.CombinedResource;
import org.eclipse.jetty.util.resource.Resource;
@ -237,11 +238,17 @@ public class JettyServletWebServerFactory extends AbstractServletWebServerFactor
handler = applyWrapper(handler, JettyHandlerWrappers.createServerHeaderHandlerWrapper(getServerHeader()));
}
if (!CollectionUtils.isEmpty(getCookieSameSiteSuppliers())) {
handler = applyWrapper(handler, new SuppliedSameSiteCookieHandlerWrapper(getCookieSameSiteSuppliers()));
handler = applyWrapper(handler,
new SuppliedSameSiteCookieHandlerWrapper(getSessionCookieName(), getCookieSameSiteSuppliers()));
}
return handler;
}
private String getSessionCookieName() {
String name = getSession().getCookie().getName();
return (name != null) ? name : SessionConfig.__DefaultSessionCookie;
}
private Handler applyWrapper(Handler handler, Handler.Wrapper wrapper) {
wrapper.setHandler(handler);
return wrapper;
@ -780,9 +787,12 @@ public class JettyServletWebServerFactory extends AbstractServletWebServerFactor
private static final SetCookieParser setCookieParser = SetCookieParser.newInstance();
private final String sessionCookieName;
private final List<CookieSameSiteSupplier> suppliers;
SuppliedSameSiteCookieHandlerWrapper(List<CookieSameSiteSupplier> suppliers) {
SuppliedSameSiteCookieHandlerWrapper(String sessionCookieName, List<CookieSameSiteSupplier> suppliers) {
this.sessionCookieName = sessionCookieName;
this.suppliers = suppliers;
}
@ -794,7 +804,7 @@ public class JettyServletWebServerFactory extends AbstractServletWebServerFactor
private class SuppliedSameSiteCookieResponse extends Response.Wrapper {
private HttpFields.Mutable wrappedHeaders;
private final HttpFields.Mutable wrappedHeaders;
SuppliedSameSiteCookieResponse(Request request, Response wrapped) {
super(request, wrapped);
@ -826,7 +836,10 @@ public class JettyServletWebServerFactory extends AbstractServletWebServerFactor
private HttpField onAddSetCookieField(HttpField field) {
HttpCookie cookie = setCookieParser.parse(field.getValue());
SameSite sameSite = (cookie != null) ? getSameSite(cookie) : null;
if (cookie == null || isSessionCookie(cookie)) {
return field;
}
SameSite sameSite = getSameSite(cookie);
if (sameSite == null) {
return field;
}
@ -834,6 +847,10 @@ public class JettyServletWebServerFactory extends AbstractServletWebServerFactor
return new HttpCookieUtils.SetCookieHttpField(updatedCookie, this.compliance);
}
private boolean isSessionCookie(HttpCookie cookie) {
return SuppliedSameSiteCookieHandlerWrapper.this.sessionCookieName.equals(cookie.getName());
}
private HttpCookie buildCookieWithUpdatedSameSite(HttpCookie cookie, SameSite sameSite) {
return HttpCookie.build(cookie)
.sameSite(org.eclipse.jetty.http.HttpCookie.SameSite.from(sameSite.name()))

View File

@ -171,6 +171,7 @@ import static org.mockito.Mockito.times;
* @author Andy Wilkinson
* @author Raja Kolli
* @author Scott Frederick
* @author Moritz Halbritter
*/
@ExtendWith(OutputCaptureExtension.class)
@DirtiesUrlFactories
@ -923,6 +924,23 @@ public abstract class AbstractServletWebServerFactoryTests {
(header) -> assertThat(header).contains("controlled=test").contains("SameSite=Strict"));
}
@Test
void cookieSameSiteSuppliersShouldNotAffectSessionCookie() throws IOException, URISyntaxException {
AbstractServletWebServerFactory factory = getFactory();
factory.getSession().getCookie().setSameSite(SameSite.LAX);
factory.getSession().getCookie().setName("SESSIONCOOKIE");
factory.addCookieSameSiteSuppliers(CookieSameSiteSupplier.ofStrict());
factory.addInitializers(new ServletRegistrationBean<>(new CookieServlet(false), "/"));
this.webServer = factory.getWebServer();
this.webServer.start();
ClientHttpResponse clientResponse = getClientResponse(getLocalUrl("/"));
assertThat(clientResponse.getStatusCode()).isEqualTo(HttpStatus.OK);
List<String> setCookieHeaders = clientResponse.getHeaders().get("Set-Cookie");
assertThat(setCookieHeaders).satisfiesExactlyInAnyOrder(
(header) -> assertThat(header).contains("SESSIONCOOKIE").contains("SameSite=Lax"),
(header) -> assertThat(header).contains("test=test").contains("SameSite=Strict"));
}
@Test
protected void sslSessionTracking() {
AbstractServletWebServerFactory factory = getFactory();
@ -1762,7 +1780,7 @@ public abstract class AbstractServletWebServerFactoryTests {
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
req.getSession(true);
resp.addCookie(new Cookie("test", "test"));
if (this.addSupplierTestCookies) {