Java 为什么servlet通过ApplicationContextFacade(而不是直接)间接访问Tomcat ApplicationContext(ServletContext)

Java 为什么servlet通过ApplicationContextFacade(而不是直接)间接访问Tomcat ApplicationContext(ServletContext),java,security,tomcat,servlets,reflection,Java,Security,Tomcat,Servlets,Reflection,我正在通读Tomcat的源代码,试图找出 tomcat内部受到保护,防止servlet进行未经授权的访问。 我注意到的一件事是,servlet通过ApplicationContextFacade获得对StandardContext的访问,ApplicationContextFacade似乎充当ApplicationContext的代理,而不是允许servlet直接访问ApplicationContext 我想知道为什么ApplicationContextFacade被传递给servlet而不是A

我正在通读Tomcat的源代码,试图找出 tomcat内部受到保护,防止servlet进行未经授权的访问。 我注意到的一件事是,servlet通过ApplicationContextFacade获得对StandardContext的访问,ApplicationContextFacade似乎充当ApplicationContext的代理,而不是允许servlet直接访问ApplicationContext

我想知道为什么ApplicationContextFacade被传递给servlet而不是ApplicationContext。 我怀疑这与安全性有关(因为facade很难简化接口,所以不是典型的facade模式)。 我查看了代码,发现它基本上转发了请求(正如预期的那样),但取决于一些安全设置(例如Globals.IS_security_ENABLED和SecurityUtil.isPackageProtectionEnabled()),它似乎使用java反射来传递请求。 我知道使用反射时权限会发生变化,但我不完全确定这将如何在ApplicationContextFacade中强制执行某些安全策略

如果有人能为我澄清这一点,那就太好了

提前感谢您的帮助

链接到javadoc

链接到tomcat源:

门面代码示例:

public String getMimeType(String file) {
        if (SecurityUtil.isPackageProtectionEnabled()) {
            return (String)doPrivileged("getMimeType", new Object[]{file});
        } else {
            return context.getMimeType(file);
        }
    }
其中,上下文是关联的ApplicationContext对象 doPrivileged的定义如下:

 private Object doPrivileged(final String methodName, final Object[] params){
        try{
            return invokeMethod(context, methodName, params);
        }catch(Throwable t){
            throw new RuntimeException(t.getMessage(), t);
        }
    }
最后调用方法

private Object invokeMethod(ApplicationContext appContext,
                                final String methodName, 
                                Object[] params) 
        throws Throwable{

        try{
            Method method = (Method)objectCache.get(methodName);
            if (method == null){
                method = appContext.getClass()
                    .getMethod(methodName, (Class[])classCache.get(methodName));
                objectCache.put(methodName, method);
            }

            return executeMethod(method,appContext,params);
        } catch (Exception ex){
            handleException(ex, methodName);
            return null;
        } finally {
            params = null;
        }
    }

我认为您还需要访问另一种方法:

我会结合这个答案来看看-


我认为不受信任的代码/类加载器(webapp)可能不允许执行某些操作,因此受信任的代码(Tomcat)可以调用
doPrivileged
,以临时覆盖webapp更受限制的权限。

首先感谢您的响应并添加缺少的代码片段!好的,正如我现在看到的,web应用程序代码的访问权限受到安全管理器的限制(例如,无法访问它不是Mime类型的文件),如果没有doprivileged,调用方的有限权限将传播到tomcat,tomcat将无法访问该web应用程序的文件。通过调用doPrivileged,facade实际上会在调用期间覆盖webapp自己(受信任)的访问权限。是这样吗?他们为什么使用反射?我觉得这很正确。我猜他们使用反射将
doPrivileged
代码包含到代码库的某个部分,而不是将单个
doPrivileged
调用分散在代码库中;这种模式可能更好地让开发人员理解使用这些技巧的地方。这是一个猜测,我不确定。
468 private Object executeMethod(final Method method, 
469                              final ApplicationContext context,
470                              final Object[] params) 
471         throws PrivilegedActionException, 
472                IllegalAccessException,
473                InvocationTargetException {
474                                  
475     if (SecurityUtil.isPackageProtectionEnabled()){
476        return AccessController.doPrivileged(new PrivilegedExceptionAction(){
477             public Object run() throws IllegalAccessException, InvocationTargetException{
478                 return method.invoke(context,  params);
479             }
480         });
481     } else {
482         return method.invoke(context, params);
483     }        
484 }