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

Reply via email to