diff --git a/support/jakarta-ee/src/main/java/org/apache/shiro/ee/filters/FormResubmitSupport.java b/support/jakarta-ee/src/main/java/org/apache/shiro/ee/filters/FormResubmitSupport.java index 8ef3c8e39a..673db571b7 100644 --- a/support/jakarta-ee/src/main/java/org/apache/shiro/ee/filters/FormResubmitSupport.java +++ b/support/jakarta-ee/src/main/java/org/apache/shiro/ee/filters/FormResubmitSupport.java @@ -29,6 +29,7 @@ import static org.apache.shiro.ee.filters.FormResubmitSupportCookies.deleteCookie; import static org.apache.shiro.ee.filters.FormResubmitSupportCookies.getCookieAge; import static org.apache.shiro.ee.filters.FormResubmitSupportCookies.getSessionCookieName; +import java.net.URISyntaxException; import java.util.Collections; import org.apache.shiro.ee.filters.Forms.FallbackPredicate; import org.apache.shiro.ee.filters.ShiroFilter.WrappedSecurityManager; @@ -82,7 +83,7 @@ */ @Slf4j @NoArgsConstructor(access = AccessLevel.PRIVATE) -@SuppressWarnings("HideUtilityClassConstructor") +@SuppressWarnings({"checkstyle:HideUtilityClassConstructor", "checkstyle:MethodCount"}) public class FormResubmitSupport { static final String SHIRO_FORM_DATA_KEY = "org.apache.shiro.form-data-key"; static final String SESSION_EXPIRED_PARAMETER = "org.apache.shiro.sessionExpired"; @@ -97,6 +98,11 @@ public class FormResubmitSupport { = Pattern.compile(String.format("[\\&]?%s.\\w+=[\\w\\s:%%\\d]*", PARTIAL_VIEW)); private static final Pattern INITIAL_AMPERSAND = Pattern.compile("^\\&"); private static final String FORM_DATA_CACHE = "org.apache.shiro.form-data-cache"; + private static final String FORM_RESUBMIT_HOST = "org.apache.shiro.form-resubmit-host"; + private static final String FORM_RESUBMIT_PORT = "org.apache.shiro.form-resubmit-port"; + private static final Optional RESUBMIT_HOST = Optional.ofNullable(System.getProperty(FORM_RESUBMIT_HOST)); + private static final Optional RESUBMIT_PORT = Optional.ofNullable(System.getProperty(FORM_RESUBMIT_PORT)) + .map(Integer::valueOf); static class HttpMethod { static final String GET = "GET"; @@ -369,13 +375,22 @@ static String resubmitSavedForm(@NonNull String savedFormData, @NonNull String s originalResponse.setStatus(AUTHFAIL); return resubmitResponseCleanup(originalRequest); } - var savedRequestURI = URI.create(savedRequest); - HttpClient client = buildHttpClient(savedRequestURI, servletContext, originalRequest); - PartialAjaxResult decodedFormData = parseFormData(savedFormData, savedRequestURI, client, servletContext); - HttpRequest postRequest = constructPostRequest(savedRequestURI, decodedFormData.result); - HttpResponse response = sendResubmitRequest(client, postRequest); + URI overriddenRequestURI = overrideSavedRequestURI(URI.create(savedRequest)); + HttpClient client = buildHttpClient(overriddenRequestURI, servletContext, originalRequest); + HttpResponse response; + PartialAjaxResult decodedFormData; + try { + decodedFormData = parseFormData(savedFormData, overriddenRequestURI, client, servletContext); + HttpRequest postRequest = constructPostRequest(overriddenRequestURI, decodedFormData.result); + response = sendResubmitRequest(client, postRequest); + } catch (IOException e) { + log.warn("Unable to resubmit form to {}" + System.lineSeparator() + + "perhaps set org.apache.shiro.form-resubmit-host or " + + "org.apache.shiro.form-resubmit-port system property?", overriddenRequestURI, e); + return savedRequest; + } if (rememberedAjaxResubmit && !decodedFormData.isStatelessRequest) { - HttpRequest redirectRequest = constructPostRequest(savedRequestURI, savedFormData); + HttpRequest redirectRequest = constructPostRequest(overriddenRequestURI, savedFormData); var redirectResponse = client.send(redirectRequest, HttpResponse.BodyHandlers.ofString()); log.debug("Redirect request: {}, response: {}", redirectRequest, redirectResponse); return processResubmitResponse(redirectResponse, originalRequest, originalResponse, @@ -389,6 +404,19 @@ static String resubmitSavedForm(@NonNull String savedFormData, @NonNull String s } } + @SneakyThrows(URISyntaxException.class) + private static URI overrideSavedRequestURI(URI savedRequestURI) { + if (RESUBMIT_HOST.isPresent() || RESUBMIT_PORT.isPresent()) { + var uri = new URI(savedRequestURI.getScheme(), savedRequestURI.getRawUserInfo(), + RESUBMIT_HOST.orElse(savedRequestURI.getHost()), RESUBMIT_PORT.orElse(savedRequestURI.getPort()), + savedRequestURI.getRawPath(), savedRequestURI.getRawQuery(), savedRequestURI.getRawFragment()); + log.debug("Form Resubmit - Overriding URI {} with {}", savedRequestURI, uri); + return uri; + } else { + return savedRequestURI; + } + } + private static HttpRequest constructPostRequest(URI request, String body) { return HttpRequest.newBuilder().uri(request) .POST(HttpRequest.BodyPublishers.ofString(body)) diff --git a/support/jakarta-ee/src/main/java/org/apache/shiro/ee/listeners/EnvironmentLoaderListener.java b/support/jakarta-ee/src/main/java/org/apache/shiro/ee/listeners/EnvironmentLoaderListener.java index 0fcba304c2..bd219c0dca 100644 --- a/support/jakarta-ee/src/main/java/org/apache/shiro/ee/listeners/EnvironmentLoaderListener.java +++ b/support/jakarta-ee/src/main/java/org/apache/shiro/ee/listeners/EnvironmentLoaderListener.java @@ -13,6 +13,7 @@ */ package org.apache.shiro.ee.listeners; +import java.util.Optional; import java.util.Set; import javax.servlet.ServletContext; import javax.servlet.ServletContextEvent; @@ -61,7 +62,8 @@ public void contextInitialized(ServletContextEvent sce) { sce.getServletContext().setAttribute(FORM_RESUBMIT_DISABLED_PARAM, Boolean.TRUE); } String secureCookiesStr = sce.getServletContext().getInitParameter(FORM_RESUBMIT_SECURE_COOKIES); - if (secureCookiesStr == null || Boolean.parseBoolean(secureCookiesStr)) { + if (Optional.ofNullable(System.getProperty(FORM_RESUBMIT_SECURE_COOKIES)).map(Boolean::valueOf) + .or(() -> Optional.ofNullable(secureCookiesStr).map(Boolean::valueOf)).orElse(true)) { sce.getServletContext().setAttribute(FORM_RESUBMIT_SECURE_COOKIES, Boolean.TRUE); } else { sce.getServletContext().setAttribute(FORM_RESUBMIT_SECURE_COOKIES, Boolean.FALSE);