This is an automated email from the ASF dual-hosted git repository. lprimak pushed a commit to branch 3.x in repository https://gitbox.apache.org/repos/asf/shiro.git
commit 698a48606f117d58cf1365a7bfb6076e53dcc270 Author: lprimak <[email protected]> AuthorDate: Fri Jan 23 18:13:53 2026 -0600 fixed Jakarta EE ITs --- .../jakarta-ee/src/main/webapp/WEB-INF/web.xml | 4 ++ .../shiro/ee/filters/FormResubmitSupport.java | 21 +++++-- .../src/main/resources/META-INF/beans.xml | 2 +- .../apache/shiro/ee/filters/FormSupportTest.java | 66 ++++++++++++++++++++-- 4 files changed, 84 insertions(+), 9 deletions(-) diff --git a/integration-tests/jakarta-ee/src/main/webapp/WEB-INF/web.xml b/integration-tests/jakarta-ee/src/main/webapp/WEB-INF/web.xml index 837c25777..cead2eaec 100644 --- a/integration-tests/jakarta-ee/src/main/webapp/WEB-INF/web.xml +++ b/integration-tests/jakarta-ee/src/main/webapp/WEB-INF/web.xml @@ -66,6 +66,10 @@ <param-name>org.apache.shiro.ee.disabled</param-name> <param-value>false</param-value> </context-param> + <context-param> + <param-name>org.apache.shiro.form-resubmit.secure-cookies</param-name> + <param-value>false</param-value> + </context-param> <!-- Apache Shiro Security --> <context-param> 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 64d54e3e7..766ad2496 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 @@ -94,9 +94,13 @@ public class FormResubmitSupport { private static final String FACES_VIEW_STATE_EQUALS = FACES_VIEW_STATE + "="; private static final Pattern VIEW_STATE_PATTERN = Pattern.compile(String.format("(.*)(%s[-]?[\\d]+:[-]?[\\d]+)(.*)", FACES_VIEW_STATE_EQUALS)); - private static final String PARTIAL_VIEW = "jakarta.faces.partial"; + private static final String FACES_SOURCE = "jakarta.faces.source"; + private static final String FACES_SOURCE_EQUALS = FACES_SOURCE + "="; + static final Pattern FACES_SOURCE_PATTERN + = Pattern.compile(String.format("[\\&]?%s([\\w\\s:%%\\d]*)(.*)", FACES_SOURCE_EQUALS)); private static final Pattern PARTIAL_REQUEST_PATTERN - = Pattern.compile("[\\&]?%s.\\w+=[\\w\\s:%%\\d]*".formatted(PARTIAL_VIEW)); + = Pattern.compile("[\\&]?(%s.\\w+|%s.\\w+|%s)=[\\w\\s:%%\\d]*".formatted( + "jakarta.faces.partial", "jakarta.faces.behavior", FACES_SOURCE)); 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"; @@ -571,8 +575,17 @@ public class FormResubmitSupport { static PartialAjaxResult noJSFAjaxRequests(String savedFormData, boolean isStateless) { var partialMatcher = PARTIAL_REQUEST_PATTERN.matcher(savedFormData); boolean hasPartialAjax = partialMatcher.find(); - return new PartialAjaxResult(isStateless ? savedFormData : INITIAL_AMPERSAND.matcher(partialMatcher - .replaceAll("")).replaceFirst(""), hasPartialAjax, isStateless); + String appendFacesSourceString = ""; + if (hasPartialAjax) { + var facesSourceMatcher = FACES_SOURCE_PATTERN.matcher(savedFormData); + if (facesSourceMatcher.find()) { + appendFacesSourceString = "&%s=".formatted(facesSourceMatcher.group(1)); + } + } + + return new PartialAjaxResult((isStateless ? savedFormData : INITIAL_AMPERSAND.matcher(partialMatcher + .replaceAll("")).replaceFirst("")) + + appendFacesSourceString, hasPartialAjax, isStateless); } static boolean isJSFStatefulForm(@NonNull String savedFormData) { diff --git a/support/jakarta-ee/src/main/resources/META-INF/beans.xml b/support/jakarta-ee/src/main/resources/META-INF/beans.xml index 40a7b1253..bafcd0a7b 100644 --- a/support/jakarta-ee/src/main/resources/META-INF/beans.xml +++ b/support/jakarta-ee/src/main/resources/META-INF/beans.xml @@ -20,5 +20,5 @@ <beans xmlns="https://jakarta.ee/xml/ns/jakartaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/beans_4_0.xsd" - bean-discovery-mode="all" version="4.0"> + bean-discovery-mode="annotated" version="4.0"> </beans> diff --git a/support/jakarta-ee/src/test/java/org/apache/shiro/ee/filters/FormSupportTest.java b/support/jakarta-ee/src/test/java/org/apache/shiro/ee/filters/FormSupportTest.java index 0ed7eb68e..8272823d8 100644 --- a/support/jakarta-ee/src/test/java/org/apache/shiro/ee/filters/FormSupportTest.java +++ b/support/jakarta-ee/src/test/java/org/apache/shiro/ee/filters/FormSupportTest.java @@ -15,6 +15,7 @@ package org.apache.shiro.ee.filters; import org.apache.shiro.ee.filters.FormResubmitSupport.PartialAjaxResult; +import static org.apache.shiro.ee.filters.FormResubmitSupport.FACES_SOURCE_PATTERN; import static org.apache.shiro.ee.filters.FormResubmitSupport.extractJSFNewViewState; import static org.apache.shiro.ee.filters.FormResubmitSupport.getReferer; import static org.apache.shiro.ee.filters.FormResubmitSupport.isJSFStatefulForm; @@ -42,7 +43,7 @@ import org.mockito.junit.jupiter.MockitoExtension; * Resubmit forms support */ @ExtendWith(MockitoExtension.class) -public class FormSupportTest { +class FormSupportTest { @Mock private HttpServletRequest request; @@ -139,9 +140,66 @@ public class FormSupportTest { + "&jakarta.faces.behavior.event=action" + "&jakarta.faces.partial.ajax=false", false)) .isEqualTo(new PartialAjaxResult("j_idt12=j_idt12&j_idt12:j_idt14=asdf&j_idt12:j_idt16=asdf" - + "&jakarta.faces.ViewState=7709788254588873136:-8052771455757429917" - + "&jakarta.faces.source=j_idt12:j_idt18" - + "&jakarta.faces.behavior.event=action", true, false)); + + "&jakarta.faces.ViewState=7709788254588873136:-8052771455757429917&j_idt12:j_idt18=", + true, false)); + } + + @Test + void parseFacesSources() { + var matcher = FACES_SOURCE_PATTERN.matcher("j_idt12=j_idt12&j_idt12:j_idt14=asdf&j_idt12:j_idt16=asdf" + + "&jakarta.faces.ViewState=7709788254588873136:-8052771455757429917" + + "&jakarta.faces.source=j_idt12:j_idt18" + + "&jakarta.faces.partial.event=click" + + "&jakarta.faces.partial.execute=j_idt12:j_idt18 j_idt12" + + "&jakarta.faces.partial.render=j_idt12" + + "&jakarta.faces.behavior.event=action" + + "&jakarta.faces.partial.ajax=false"); + assertThat(matcher.find()).isTrue(); + assertThat(matcher.group(1)).isEqualTo("j_idt12:j_idt18"); + } + + @Test + void clientSideStateSavingNoAjax() { + String savedRequest = """ + secondForm=secondForm&secondForm:address=asfd&secondForm:city=asdf + &jakarta.faces.ViewState=5BDAqkysYaMvzcnTG3bVSXRoK43OvdMyb8w6RicBatqzOdHBwl/cFvOXYfYCwvJoBU6/qv + 735kadAP67luQ/wMqF4jAQyBKDdxy5F4CxNz4FhAYC2iCd613QnwLWP8BX3so7BylQxIN2Y64n6LUogwkgZLEAHgTBDQGwG + F2SMhdkehYjYo5/IwRP2rrlE0DAWU7gYMeqRFutzwi7wJ5pBYc9zxA3D/TzJofi8ssR3vED2b3y5Xz8nLLgzK7Zz2Kf4YDQ + BoiX/FLoL+qeNY7ooL+2/kphH1RuxqcFVM9izcq5Egqk0m7DvN5LB6a6JRH+yEgmBhi1Ns4k89FFcrSfu8pyD4gk8ZVMvQL + P2dRSBSMW3/ECkrbQelN5NyRKls9cdU8htkxYTfJmceLQGcw7FlU63KJFOkUCk+QUzQzjJL90RJ/nu/Efpq/U6tIsSZJVAO + 8xyQaqoV38Q/5PVdvl23zapm/WlbtDDOuKoE5ToXCh2s43Gf8VIK+dXkwTLsgsbgt4GrTSHdT9GYA7aE8TDC/gTqDhbkLM7 + QjIdmCT7ELQVplSKOoQg5YPRPpAAswyxsFHtuwE7k9sLzORp0GhPfehryKEHJDL4AZJA1jTdTDZAKl3qU1bvp4kBOE5STj5 + s1cDihxs+hWgEuuZsN0CDP06AUBlHE6ALmE52oH9CL4N+pAiUy3mlbVloM83+pfIyC4h3b8AnvDdlw788NiFA3mgsQQTX2v + lbAemEX2+50CobUjfx3bVo+jWBEyaAGJmWLFA6Jo4MD8xFeIST7Q/kME+GMtlR1ePE3E9a7jCb3Nt3dPLotjWGpSUg4n7Y+ + 5uvxdvth9U0PQF8G0+so1MAWTrmCTZS1c15xuAk/lfOsP9viwls6UdfdA1nhzypizwUuIgsHKwxz92j+RXs9fz1uaQdldcC + O51Rj2eMsIHdls+sz6XsXcSfJq2k8OJMBMHqAW4fu4lVoKhL6uLupvMgqdM7gF777/9ejg7RuFdT4lYpVYnSYFprCBUSz/q + Vbz4b2Rre7zhBzUIxfa2KNHgWhIFD94M+zZI1mbXfN7OtcjPHY9pCxP1jinmlLrPcR9rjXZgSbOtyQSHFyj9VN3ry2ySMj7 + +pPVPIhNPE8PoYj9psBzneUQJJLrSJN1d7aW+ + &jakarta.faces.source=secondForm:submitSecond + &jakarta.faces.partial.event=click + &jakarta.faces.partial.execute=secondForm:submitSecond secondForm + &jakarta.faces.partial.render=secondForm&jakarta.faces.behavior.event=action + &jakarta.faces.partial.ajax=true""".replace("\n", ""); + assertThat(noJSFAjaxRequests(savedRequest, true).result).isEqualTo(""" + secondForm=secondForm&secondForm:address=asfd&secondForm:city=asdf + &jakarta.faces.ViewState=5BDAqkysYaMvzcnTG3bVSXRoK43OvdMyb8w6RicBatqzOdHBwl/cFvOXYfYCwvJoBU6/qv + 735kadAP67luQ/wMqF4jAQyBKDdxy5F4CxNz4FhAYC2iCd613QnwLWP8BX3so7BylQxIN2Y64n6LUogwkgZLEAHgTBDQGwG + F2SMhdkehYjYo5/IwRP2rrlE0DAWU7gYMeqRFutzwi7wJ5pBYc9zxA3D/TzJofi8ssR3vED2b3y5Xz8nLLgzK7Zz2Kf4YDQ + BoiX/FLoL+qeNY7ooL+2/kphH1RuxqcFVM9izcq5Egqk0m7DvN5LB6a6JRH+yEgmBhi1Ns4k89FFcrSfu8pyD4gk8ZVMvQL + P2dRSBSMW3/ECkrbQelN5NyRKls9cdU8htkxYTfJmceLQGcw7FlU63KJFOkUCk+QUzQzjJL90RJ/nu/Efpq/U6tIsSZJVAO + 8xyQaqoV38Q/5PVdvl23zapm/WlbtDDOuKoE5ToXCh2s43Gf8VIK+dXkwTLsgsbgt4GrTSHdT9GYA7aE8TDC/gTqDhbkLM7 + QjIdmCT7ELQVplSKOoQg5YPRPpAAswyxsFHtuwE7k9sLzORp0GhPfehryKEHJDL4AZJA1jTdTDZAKl3qU1bvp4kBOE5STj5 + s1cDihxs+hWgEuuZsN0CDP06AUBlHE6ALmE52oH9CL4N+pAiUy3mlbVloM83+pfIyC4h3b8AnvDdlw788NiFA3mgsQQTX2v + lbAemEX2+50CobUjfx3bVo+jWBEyaAGJmWLFA6Jo4MD8xFeIST7Q/kME+GMtlR1ePE3E9a7jCb3Nt3dPLotjWGpSUg4n7Y+ + 5uvxdvth9U0PQF8G0+so1MAWTrmCTZS1c15xuAk/lfOsP9viwls6UdfdA1nhzypizwUuIgsHKwxz92j+RXs9fz1uaQdldcC + O51Rj2eMsIHdls+sz6XsXcSfJq2k8OJMBMHqAW4fu4lVoKhL6uLupvMgqdM7gF777/9ejg7RuFdT4lYpVYnSYFprCBUSz/q + Vbz4b2Rre7zhBzUIxfa2KNHgWhIFD94M+zZI1mbXfN7OtcjPHY9pCxP1jinmlLrPcR9rjXZgSbOtyQSHFyj9VN3ry2ySMj7 + +pPVPIhNPE8PoYj9psBzneUQJJLrSJN1d7aW+ + &jakarta.faces.source=secondForm:submitSecond + &jakarta.faces.partial.event=click + &jakarta.faces.partial.execute=secondForm:submitSecond secondForm + &jakarta.faces.partial.render=secondForm&jakarta.faces.behavior.event=action + &jakarta.faces.partial.ajax=true&secondForm:submitSecond=""".replace("\n", "")); } @Test
