Просмотр исходного кода

SEC-2066: ProtectPointcutPostProcessor is now ThreadSafe

Previously a ConcurrentModificationException could occur when
PointcutExpression.matchesMethodExecution was performed in multiple threads. Another
issue was that beans may get processed multiple times.

Now a lock is performed to ensure that only a single thread has access to
PointcutExpression.matchesMethodExecution and that each bean only gets processed once.
Rob Winch 12 лет назад
Родитель
Сommit
1a7aaa85c4

+ 24 - 15
config/src/main/java/org/springframework/security/config/method/ProtectPointcutPostProcessor.java

@@ -51,6 +51,7 @@ final class ProtectPointcutPostProcessor implements BeanPostProcessor {
     private final PointcutParser parser;
     private final Set<String> processedBeans = new HashSet<String>();
 
+
     public ProtectPointcutPostProcessor(MapBasedMethodSecurityMetadataSource mapBasedMethodSecurityMetadataSource) {
         Assert.notNull(mapBasedMethodSecurityMetadataSource, "MapBasedMethodSecurityMetadataSource to populate is required");
         this.mapBasedMethodSecurityMetadataSource = mapBasedMethodSecurityMetadataSource;
@@ -80,26 +81,34 @@ final class ProtectPointcutPostProcessor implements BeanPostProcessor {
             return bean;
         }
 
-        // Obtain methods for the present bean
-        Method[] methods;
-        try {
-            methods = bean.getClass().getMethods();
-        } catch (Exception e) {
-            throw new IllegalStateException(e.getMessage());
-        }
+        synchronized(processedBeans) {
+            // check again synchronized this time
+            if (processedBeans.contains(beanName)) {
+                return bean;
+            }
 
-        // Check to see if any of those methods are compatible with our pointcut expressions
-        for (Method method : methods) {
-            for (PointcutExpression expression : pointCutExpressions) {
-                // Try for the bean class directly
-                if (attemptMatch(bean.getClass(), method, expression, beanName)) {
-                    // We've found the first expression that matches this method, so move onto the next method now
-                    break; // the "while" loop, not the "for" loop
+            // Obtain methods for the present bean
+            Method[] methods;
+            try {
+                methods = bean.getClass().getMethods();
+            } catch (Exception e) {
+                throw new IllegalStateException(e.getMessage());
+            }
+
+            // Check to see if any of those methods are compatible with our pointcut expressions
+            for (Method method : methods) {
+                for (PointcutExpression expression : pointCutExpressions) {
+                    // Try for the bean class directly
+                    if (attemptMatch(bean.getClass(), method, expression, beanName)) {
+                        // We've found the first expression that matches this method, so move onto the next method now
+                        break; // the "while" loop, not the "for" loop
+                    }
                 }
             }
+
+            processedBeans.add(beanName);
         }
 
-        processedBeans.add(beanName);
 
         return bean;
     }