This is an automated email from the ASF dual-hosted git repository.

robertlazarski pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/axis-axis2-java-core.git

commit db3e3ba6e8d50225204c8eb8fc3ee8f94f108f23
Author: Zibran Khan <[email protected]>
AuthorDate: Mon Oct 26 20:18:59 2026 +0530

    generate standalone http session keys from a secure random source
---
 .../transport/http/server/SessionManager.java      |  2 +-
 .../axis2/transport/server/SessionManagerTest.java | 38 ++++++++++++++++++++++
 2 files changed, 39 insertions(+), 1 deletion(-)

diff --git 
a/modules/transport/http/src/main/java/org/apache/axis2/transport/http/server/SessionManager.java
 
b/modules/transport/http/src/main/java/org/apache/axis2/transport/http/server/SessionManager.java
index c3e6f2ce84..e44c3b6328 100644
--- 
a/modules/transport/http/src/main/java/org/apache/axis2/transport/http/server/SessionManager.java
+++ 
b/modules/transport/http/src/main/java/org/apache/axis2/transport/http/server/SessionManager.java
@@ -44,7 +44,7 @@ public class SessionManager {
             sessionContext = (SessionContext) this.sessionmap.get(sessionKey);
         }
         if (sessionContext == null) {
-            sessionKey = UIDGenerator.generateUID();
+            sessionKey = UIDGenerator.generateURNString();
             sessionContext = new SessionContext(null);
             sessionContext.setCookieID(sessionKey);
             this.sessionmap.put(sessionKey, sessionContext);
diff --git 
a/modules/transport/http/src/test/java/org/apache/axis2/transport/server/SessionManagerTest.java
 
b/modules/transport/http/src/test/java/org/apache/axis2/transport/server/SessionManagerTest.java
index 16b86eba19..a98d2b94d5 100644
--- 
a/modules/transport/http/src/test/java/org/apache/axis2/transport/server/SessionManagerTest.java
+++ 
b/modules/transport/http/src/test/java/org/apache/axis2/transport/server/SessionManagerTest.java
@@ -72,4 +72,42 @@ public class SessionManagerTest extends TestCase {
         assertFalse(sessionKey.equals(ctx3.getCookieID()));
     }
 
+    /**
+     * The session key is the only credential a caller needs to be bound to a
+     * SessionContext, so the next one must not follow from the last. A key 
built
+     * from a per-thread counter differs from its predecessor only by the low 
bits
+     * that change on increment, which leaves at most 64 candidates.
+     */
+    public void testSessionKeyNotPredictableFromPreviousKey() {
+        for (int i = 0; i < 100; i++) {
+            String previous = manager.getSessionContext(null).getCookieID();
+            String next = manager.getSessionContext(null).getCookieID();
+            for (int t = 0; t < 64; t++) {
+                long mask = t == 63 ? -1L : (1L << (t + 1)) - 1;
+                assertFalse(next.equals(flipCounterBits(previous, mask)));
+            }
+        }
+    }
+
+    // Applies mask to the reversed-hex counter that leads a counter-based key.
+    private static String flipCounterBits(String key, long mask) {
+        if (key.length() < 16) {
+            return null;
+        }
+        long counter = 0;
+        for (int i = 0; i < 16; i++) {
+            int nibble = Character.digit(key.charAt(i), 16);
+            if (nibble < 0) {
+                return null;
+            }
+            counter |= (long) nibble << (4 * i);
+        }
+        counter ^= mask;
+        StringBuilder buffer = new StringBuilder(key.length());
+        for (int i = 0; i < 16; i++) {
+            buffer.append(Character.forDigit((int) (counter >> (4 * i)) & 15, 
16));
+        }
+        return buffer.append(key.substring(16)).toString();
+    }
+
 }

Reply via email to