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

heliang666s pushed a commit to branch 3.3
in repository https://gitbox.apache.org/repos/asf/dubbo.git


The following commit(s) were added to refs/heads/3.3 by this push:
     new bcc220ad4b Fix #15988: Clear SecurityContext in finally block to 
prevent thread pollution (#15997)
bcc220ad4b is described below

commit bcc220ad4b9b071bde405ffccef30f6907a8677c
Author: Shivvani Ramadugu <[email protected]>
AuthorDate: Wed Jan 14 13:15:29 2026 +0530

    Fix #15988: Clear SecurityContext in finally block to prevent thread 
pollution (#15997)
---
 .../ContextHolderAuthenticationResolverFilter.java |  8 ++-
 ...textHolderAuthenticationResolverFilterTest.java | 68 ++++++++++++++++++++++
 2 files changed, 75 insertions(+), 1 deletion(-)

diff --git 
a/dubbo-plugin/dubbo-spring-security/src/main/java/org/apache/dubbo/spring/security/filter/ContextHolderAuthenticationResolverFilter.java
 
b/dubbo-plugin/dubbo-spring-security/src/main/java/org/apache/dubbo/spring/security/filter/ContextHolderAuthenticationResolverFilter.java
index 0183938b54..6a74864340 100644
--- 
a/dubbo-plugin/dubbo-spring-security/src/main/java/org/apache/dubbo/spring/security/filter/ContextHolderAuthenticationResolverFilter.java
+++ 
b/dubbo-plugin/dubbo-spring-security/src/main/java/org/apache/dubbo/spring/security/filter/ContextHolderAuthenticationResolverFilter.java
@@ -61,7 +61,13 @@ public class ContextHolderAuthenticationResolverFilter 
implements Filter {
             getSecurityContext(invocation);
         }
 
-        return invoker.invoke(invocation);
+        try {
+            return invoker.invoke(invocation);
+        } finally {
+            if (this.mapper != null) {
+                SecurityContextHolder.clearContext();
+            }
+        }
     }
 
     private void getSecurityContext(Invocation invocation) {
diff --git 
a/dubbo-plugin/dubbo-spring-security/src/test/java/org/apache/dubbo/spring/security/filter/ContextHolderAuthenticationResolverFilterTest.java
 
b/dubbo-plugin/dubbo-spring-security/src/test/java/org/apache/dubbo/spring/security/filter/ContextHolderAuthenticationResolverFilterTest.java
new file mode 100644
index 0000000000..a2109416f0
--- /dev/null
+++ 
b/dubbo-plugin/dubbo-spring-security/src/test/java/org/apache/dubbo/spring/security/filter/ContextHolderAuthenticationResolverFilterTest.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.spring.security.filter;
+
+import org.apache.dubbo.common.beans.factory.ScopeBeanFactory;
+import org.apache.dubbo.rpc.AppResponse;
+import org.apache.dubbo.rpc.Invocation;
+import org.apache.dubbo.rpc.Invoker;
+import org.apache.dubbo.rpc.model.ApplicationModel;
+import org.apache.dubbo.spring.security.jackson.ObjectMapperCodec;
+
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Test;
+import 
org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+class ContextHolderAuthenticationResolverFilterTest {
+
+    @AfterEach
+    public void cleanup() {
+        SecurityContextHolder.clearContext();
+    }
+
+    @Test
+    void testSecurityContextIsClearedAfterInvoke() {
+        ApplicationModel applicationModel = mock(ApplicationModel.class);
+        ScopeBeanFactory beanFactory = mock(ScopeBeanFactory.class);
+        ObjectMapperCodec codec = mock(ObjectMapperCodec.class);
+
+        when(applicationModel.getBeanFactory()).thenReturn(beanFactory);
+        when(beanFactory.getBean(ObjectMapperCodec.class)).thenReturn(codec);
+
+        ContextHolderAuthenticationResolverFilter filter =
+                new 
ContextHolderAuthenticationResolverFilter(applicationModel);
+
+        Invocation invocation = mock(Invocation.class);
+        Invoker<?> invoker = mock(Invoker.class);
+
+        when(invoker.invoke(any(Invocation.class))).thenReturn(new 
AppResponse());
+        SecurityContextHolder.getContext()
+                .setAuthentication(new 
UsernamePasswordAuthenticationToken("user", "password"));
+        filter.invoke(invoker, invocation);
+        Authentication auth = 
SecurityContextHolder.getContext().getAuthentication();
+
+        assertNull(
+                auth, "SecurityContext must be cleared after the filter chain 
completes to prevent thread pollution.");
+    }
+}

Reply via email to