tomcat8.0 and tomcat8.5.6 WebappClassLoaderBase

风流意气都作罢 提交于 2019-12-24 07:59:52

问题


We update tomcat to 8.5.6 from 8.0.32 recently, and we meet a AccessControlException when try to load /opt/apache-tomcat-8.5.6_1/webapps/example/WEB-INF/classes/com/sun/xml/internal/ws/runtime/config/jaxb.properties, and I debug the source code between tomcat 8.5.6 and 8.0.32, it's different in org.apache.catalina.loader.WebappClassLoaderBase.findResource

Tomcat8.0

public URL findResource(final String name) {

    if (log.isDebugEnabled())
        log.debug("    findResource(" + name + ")");

    checkStateForResourceLoading(name);

    URL url = null;

    String path = nameToPath(name);

    ResourceEntry entry = resourceEntries.get(path);
    if (entry == null) {
        if (securityManager != null) {
            PrivilegedAction<ResourceEntry> dp =
                new PrivilegedFindResourceByName(name, path);
            entry = AccessController.doPrivileged(dp);
        } else {
            entry = findResourceInternal(name, path);
        }
    }
    if (entry != null) {
        url = entry.source;
        entry.webResource = null;
    }

    if ((url == null) && hasExternalRepositories) {
        url = super.findResource(name);
    }

    if (log.isDebugEnabled()) {
        if (url != null)
            log.debug("    --> Returning '" + url.toString() + "'");
        else
            log.debug("    --> Resource not found, returning null");
    }
    return url;
}

Tomcat8.5.6

public URL findResource(final String name) {

    if (log.isDebugEnabled())
        log.debug("    findResource(" + name + ")");

    checkStateForResourceLoading(name);

    URL url = null;

    String path = nameToPath(name);

    WebResource resource = resources.getClassLoaderResource(path);
    if (resource.exists()) {
        url = resource.getURL();
        trackLastModified(path, resource);
    }

    if ((url == null) && hasExternalRepositories) {
        url = super.findResource(name);
    }

    if (log.isDebugEnabled()) {
        if (url != null)
            log.debug("    --> Returning '" + url.toString() + "'");
        else
            log.debug("    --> Resource not found, returning null");
    }
    return url;
}

As you can see, tomcat8.0 load resource by AccessController.doPrivileged, but in tomcat8.5.6, it load the resource directly, I think that's why I got a Exception

java.security.AccessControlException: access denied 
("java.io.FilePermission" 
"/opt/apache-tomcat-8.5.6_1/webapps/example/WEB-INF/classes/com/sun/xml/internal/ws/runtime/config/jaxb.properties" 
"read")

java.lang.IllegalStateException: MASM0003: Default [ jaxws-tubes-default.xml ] configuration file was not loaded
        at com.sun.xml.internal.ws.assembler.MetroConfigLoader.init(MetroConfigLoader.java:133)
        at com.sun.xml.internal.ws.assembler.MetroConfigLoader.<init>(MetroConfigLoader.java:104)

this file is loaded by MetroConfigLoader,

private static JAXBContext createJAXBContext() throws Exception {
        return isJDKInternal()?(JAXBContext)AccessController.doPrivileged(new PrivilegedExceptionAction<JAXBContext>() {
            public JAXBContext run() throws Exception {
                return JAXBContext.newInstance(MetroConfig.class.getPackage().getName());
            }
        }, createSecurityContext()):JAXBContext.newInstance(MetroConfig.class.getPackage().getName());
    }

    private static AccessControlContext createSecurityContext() {
        PermissionCollection perms = new Permissions();
        perms.add(new RuntimePermission("accessClassInPackage.com.sun.xml.internal.ws.runtime.config"));
        perms.add(new ReflectPermission("suppressAccessChecks"));
        return new AccessControlContext(new ProtectionDomain[]{new ProtectionDomain((CodeSource)null, perms)});
    }

Does anyone meet same issue? or there is some other issues. thanks.


回答1:


After three days researching, now I use jaxws-rt instead of default implementation in JDK, and as you can read from the code in JDK:

private static JAXBContext createJAXBContext() throws Exception {
        return isJDKInternal()?(JAXBContext)AccessController.doPrivileged(new PrivilegedExceptionAction<JAXBContext>() {
            public JAXBContext run() throws Exception {
                return JAXBContext.newInstance(MetroConfig.class.getPackage().getName());
            }
        }, createSecurityContext()):JAXBContext.newInstance(MetroConfig.class.getPackage().getName());
}

If it's JDK internal, it will create the instance with specific privilege, and tomcat get resource by doPrivileged in tomcat8.0, but it's different in tomcat8.5, So it can't get the resource without privilege

java.security.AccessControlException: access denied ("java.io.FilePermission" 
"/opt/apache-tomcat-8.5.6_1/webapps/example/WEB-INF/classes/com/sun/xml/internal/ws/runtime/config/jaxb.properties" 
"read")

So I changed to external jaxws-rt, and it will create the instance directly. I just add jaxws-rt to pom.

 <dependency>
        <groupId>com.sun.xml.ws</groupId>
        <artifactId>jaxws-rt</artifactId>
        <version>2.2.10</version>
 </dependency>


来源:https://stackoverflow.com/questions/44212443/tomcat8-0-and-tomcat8-5-6-webappclassloaderbase

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!