You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by ff...@apache.org on 2018/10/27 05:38:58 UTC

[cxf] branch master updated: [CXF-7838]Remove illegal reflective access in CXFAuthenticator

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

ffang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cxf.git


The following commit(s) were added to refs/heads/master by this push:
     new 818d7fc  [CXF-7838]Remove illegal reflective access in CXFAuthenticator
     new 39ae7d5  Merge branch 'master' of github.com:apache/cxf
818d7fc is described below

commit 818d7fc2d21cee96ec5e47c6d914403ebcaeb184
Author: Freeman Fang <fr...@gmail.com>
AuthorDate: Sat Oct 27 13:38:12 2018 +0800

    [CXF-7838]Remove illegal reflective access in CXFAuthenticator
---
 .../cxf/transport/http/CXFAuthenticator.java       | 89 +++++++++++++++-------
 .../http/CXFAuthenticatorCleanupTest.java          | 11 ++-
 2 files changed, 69 insertions(+), 31 deletions(-)

diff --git a/rt/transports/http/src/main/java/org/apache/cxf/transport/http/CXFAuthenticator.java b/rt/transports/http/src/main/java/org/apache/cxf/transport/http/CXFAuthenticator.java
index b8d97eb..a7ff62c 100644
--- a/rt/transports/http/src/main/java/org/apache/cxf/transport/http/CXFAuthenticator.java
+++ b/rt/transports/http/src/main/java/org/apache/cxf/transport/http/CXFAuthenticator.java
@@ -21,6 +21,7 @@ package org.apache.cxf.transport.http;
 
 import java.io.InputStream;
 import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.net.Authenticator;
 import java.net.PasswordAuthentication;
@@ -31,6 +32,7 @@ import java.security.PrivilegedAction;
 
 import org.apache.cxf.common.util.ReflectionUtil;
 import org.apache.cxf.helpers.IOUtils;
+import org.apache.cxf.helpers.JavaUtils;
 import org.apache.cxf.message.Exchange;
 import org.apache.cxf.message.Message;
 import org.apache.cxf.phase.PhaseInterceptorChain;
@@ -50,40 +52,75 @@ public class CXFAuthenticator extends Authenticator {
         if (instance == null) {
             instance = new CXFAuthenticator();
             Authenticator wrapped = null;
-            for (final Field f : ReflectionUtil.getDeclaredFields(Authenticator.class)) {
-                if (f.getType().equals(Authenticator.class)) {
-                    ReflectionUtil.setAccessible(f);
-                    try {
-                        wrapped = (Authenticator)f.get(null);
-                        if (wrapped != null
-                            && wrapped.getClass().getName().equals(ReferencingAuthenticator.class.getName())) {
-                            Method m = wrapped.getClass().getMethod("check");
-                            m.setAccessible(true);
-                            m.invoke(wrapped);
+            if (JavaUtils.isJava9Compatible()) {
+                try {
+                    Method m = ReflectionUtil.getMethod(Authenticator.class, "getDefault");
+                    wrapped = (Authenticator)m.invoke(null);
+                } catch (Exception e) {
+                    // ignore
+                }
+                
+
+            } else {
+                for (final Field f : ReflectionUtil.getDeclaredFields(Authenticator.class)) {
+                    if (f.getType().equals(Authenticator.class)) {
+                        ReflectionUtil.setAccessible(f);
+                        try {
+                            wrapped = (Authenticator)f.get(null);
+                            if (wrapped != null && wrapped.getClass().getName()
+                                .equals(ReferencingAuthenticator.class.getName())) {
+                                Method m = wrapped.getClass().getMethod("check");
+                                m.setAccessible(true);
+                                m.invoke(wrapped);
+                            }
+                            wrapped = (Authenticator)f.get(null);
+                        } catch (Exception e) {
+                            // ignore
                         }
-                        wrapped = (Authenticator)f.get(null);
-                    } catch (Exception e) {
-                        //ignore
                     }
                 }
             }
 
             try {
-                ClassLoader loader = AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
+                Class<?> cls = null;
+                InputStream ins = ReferencingAuthenticator.class
+                    .getResourceAsStream("ReferencingAuthenticator.class");
+                byte[] b = IOUtils.readBytesFromStream(ins);
+                if (JavaUtils.isJava9Compatible()) {
+                    Class<?> methodHandles = Class.forName("java.lang.invoke.MethodHandles");
+                    Method m = ReflectionUtil.getMethod(methodHandles, "lookup");
+                    Object lookup = m.invoke(null);
+                    m = ReflectionUtil.getMethod(lookup.getClass(), "findClass", String.class);
+                    try {
+                        cls = (Class<?>)m.invoke(lookup, "org.apache.cxf.transport.http.ReferencingAuthenticator");
+                    } catch (InvocationTargetException e) {
+                        //use defineClass as fallback
+                        m = ReflectionUtil.getMethod(lookup.getClass(), "defineClass", byte[].class);
+                        cls = (Class<?>)m.invoke(lookup, b);
+                    }
+                } else {
+                    ClassLoader loader = AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
                         public ClassLoader run() {
                             return new URLClassLoader(new URL[0], ClassLoader.getSystemClassLoader());
                         }
                     }, null);
-                Method m = ReflectionUtil.getDeclaredMethod(ClassLoader.class, "defineClass", String.class,
-                                                               byte[].class, Integer.TYPE, Integer.TYPE);
+                    Method m = ReflectionUtil.getDeclaredMethod(ClassLoader.class, "defineClass",
+                                                                String.class, byte[].class, Integer.TYPE,
+                                                                Integer.TYPE);
 
-                InputStream ins = ReferencingAuthenticator.class
-                        .getResourceAsStream("ReferencingAuthenticator.class");
-                byte[] b = IOUtils.readBytesFromStream(ins);
+                    
 
-                ReflectionUtil.setAccessible(m).invoke(loader, ReferencingAuthenticator.class.getName(),
-                                                       b, 0, b.length);
-                Class<?> cls = loader.loadClass(ReferencingAuthenticator.class.getName());
+                    ReflectionUtil.setAccessible(m).invoke(loader, ReferencingAuthenticator.class.getName(),
+                                                           b, 0, b.length);
+                    cls = loader.loadClass(ReferencingAuthenticator.class.getName());
+                    try {
+                        //clear the acc field that can hold onto the webapp classloader
+                        Field f = ReflectionUtil.getDeclaredField(loader.getClass(), "acc");
+                        ReflectionUtil.setAccessible(f).set(loader, null);
+                    } catch (Throwable t) {
+                        //ignore
+                    }
+                }
                 final Authenticator auth = (Authenticator)cls.getConstructor(Authenticator.class, Authenticator.class)
                     .newInstance(instance, wrapped);
 
@@ -98,13 +135,7 @@ public class CXFAuthenticator extends Authenticator {
                     });
 
                 }
-                try {
-                    //clear the acc field that can hold onto the webapp classloader
-                    Field f = ReflectionUtil.getDeclaredField(loader.getClass(), "acc");
-                    ReflectionUtil.setAccessible(f).set(loader, null);
-                } catch (Throwable t) {
-                    //ignore
-                }
+                
             } catch (Throwable t) {
                 //ignore
             }
diff --git a/rt/transports/http/src/test/java/org/apache/cxf/transport/http/CXFAuthenticatorCleanupTest.java b/rt/transports/http/src/test/java/org/apache/cxf/transport/http/CXFAuthenticatorCleanupTest.java
index 7035d59..1e2215f 100644
--- a/rt/transports/http/src/test/java/org/apache/cxf/transport/http/CXFAuthenticatorCleanupTest.java
+++ b/rt/transports/http/src/test/java/org/apache/cxf/transport/http/CXFAuthenticatorCleanupTest.java
@@ -137,8 +137,15 @@ public class CXFAuthenticatorCleanupTest {
         //after clear and gc's
         int none = traceLengths.get(traceLengths.size() - 1);
 
-        //System.out.println(traceLengths);
-        Assert.assertTrue(one < (raw + (20 * 2))); //one should only be slightly above raw
+        /*stacktrace for one should be different with raw
+         * but the stracktrace length in java 8 and java 9-plus
+         * isn't identical
+         * so previous assertion one < (raw + (20 * 2)
+         * isn't applicable for java 9-plus
+         */
+        Assert.assertTrue(one != raw); 
+        
+        
         Assert.assertTrue(one > raw);
         Assert.assertTrue(one > none);
         Assert.assertEquals(raw, none);