【问题标题】:Why do servlets access the Tomcat ApplicationContext (ServletContext) indirectly through the ApplicationContextFacade (rather than directly)为什么servlet通过ApplicationContextFacade间接(而不是直接)访问Tomcat ApplicationContext(ServletContext)
【发布时间】:2012-03-03 23:31:41
【问题描述】:

我正在阅读 Tomcat 源代码,试图弄清楚如何 Tomcat 内部受到保护,防止来自 servlet 的未经授权的访问。 我注意到的一件事是 servlet 通过 ApplicationContextFacade 获得对 StandardContext 的访问权,这似乎充当 ApplicationContext 的代理,而不是允许 servlet 直接访问 ApplicationContext。

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

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

提前感谢您的帮助。

链接到 javadoc http://tomcat.apache.org/tomcat-7.0-doc/api/org/apache/catalina/core/ApplicationContextFacade.html

tomcat 源码链接: http://tomcat.apache.org/download-70.cgi

门面代码示例:

public String getMimeType(String file) {
        if (SecurityUtil.isPackageProtectionEnabled()) {
            return (String)doPrivileged("getMimeType", new Object[]{file});
        } else {
            return context.getMimeType(file);
        }
    }

其中 context 是关联的 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;
        }
    }

【问题讨论】:

    标签: java security tomcat servlets reflection


    【解决方案1】:

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

    ApplicationContextFacade.executeMethod

    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 }
    

    我会结合这个答案来看看 - When should AccessController.doPrivileged() be used?

    我认为可能不允许不受信任的代码/类加载器(webapp)做某些事情,因此受信任的代码(Tomcat)可以调用doPrivileged 以暂时覆盖 webapp 的更多受限权限。

    【讨论】:

    • 首先感谢您回复并添加缺少的代码片段!好的,正如我现在所看到的,Web 应用程序代码的访问权限受到安全管理器的限制(例如,无法访问它不是 Mime 类型的文件),如果没有权限,调用者的有限权限将传播到tomcat 和 tomcat 将无法访问该 webapp 的文件。通过调用 doPrivileged,外观实际上为 webapp 提供了支持,在调用期间由它自己的(受信任的)覆盖其访问权限。那是对的吗?他们为什么使用反射?
    • 这对我来说听起来不错。我猜他们使用反射将doPrivileged 代码包含到代码库的某个部分,而不是将单独的doPrivileged 调用分散在代码库中;这种模式可能更便于开发人员理解使用这些技巧的地方。这些只是猜测,我不确定。
    猜你喜欢
    • 2018-09-17
    • 1970-01-01
    • 1970-01-01
    • 2018-06-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多