2

我正在使用 JSF 2.2。我正在尝试将 JSF 用作纯模板语言。但是,有一个问题。在我的环境中创建 JSF 页面的任何用户都可以执行以下操作:

#{session.getAttribute('user').getApiKey()}

在这里,我有一个存储在会话中的用户对象,getApiKey() 方法是该类中的 getter。

是否有“web.xml”配置或其他一些技巧可以用来在 JSF 页面上完全禁用会话对象?

4

3 回答 3

2

是否有“web.xml”配置或其他一些技巧可以用来在 JSF 页面上完全禁用会话对象?

不。

根据允许的标签、属性和 EL 表达式的白名单手动解析模板(注意:不要使用黑名单,黑客会找到你想不到的方法)。例如,以下表达式与 具有相同的效果#{session.getAttribute('user').getApiKey()}

  • #{request.session.getAttribute('user').apiKey}
  • #{sessionScope.user.apiKey}
  • #{user.apiKey}
  • #{facesContext.externalContext.sessionMap.user.apiKey}
  • #{facesContext.externalContext.session.getAttribute('user').apiKey}

毕竟,JSF/Facelets 可能是错误的工具,无法为客户提供某种将在服务器中执行的模板。而是寻找类似BB / Wiki / Markdown的标记或您通过.<h:outputText escape="false">

于 2013-04-10T21:03:12.670 回答
1

也许。隐式变量由特定的 ELResolver 提供。从 ELResolvers 列表中删除那个,或者添加一个自己的解析器,该解析器总是为该列表的所有隐式变量返回 null,应该可以解决问题。

顺便说一句,我不知道 JSF 是否提供了一个公共 API 来做这件事,或者规范甚至允许这样的事情。

无论哪种方式,如果您只需要一个模板引擎,有更简单的选项可以定制一个有状态的、基于组件的 Web 应用程序框架......

于 2013-04-10T21:27:56.437 回答
0

这是我为解决这个问题所做的。这个类本质上撤销了对页面上所有核心对象的访问。此外,我添加了一个实用程序变量来访问上下文路径。我试过这个,它似乎工作!.

package com.example.templates.jsf;

import javax.el.ELContext;
import javax.el.ELException;
import javax.el.PropertyNotFoundException;
import javax.faces.component.UIComponent;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;

import com.sun.faces.component.CompositeComponentStackManager;
import com.sun.faces.el.ImplicitObjectELResolver;
import com.sun.faces.util.MessageUtils;

/**
 *  This class revokes access to server page context objects 
 */
public class CustomImplicitObjectELResolver extends ImplicitObjectELResolver {

public static final int CONTEXT_PATH = 19;

public CustomImplicitObjectELResolver(){
    super();

    // Revoke access to variables that can potentially
    // give access to internal class objects.
    IMPLICIT_OBJECTS.remove("facesContext");
    IMPLICIT_OBJECTS.remove("session");
    IMPLICIT_OBJECTS.remove("sessionScope");
    IMPLICIT_OBJECTS.remove("application");
    IMPLICIT_OBJECTS.remove("applicationScope");
    IMPLICIT_OBJECTS.remove("request");
    IMPLICIT_OBJECTS.remove("requestScope");
    IMPLICIT_OBJECTS.remove("view");
    IMPLICIT_OBJECTS.remove("viewScope");
    IMPLICIT_OBJECTS.remove("initParam");
    IMPLICIT_OBJECTS.remove("component");       
    IMPLICIT_OBJECTS.remove("cookie");
    IMPLICIT_OBJECTS.remove("header");
    IMPLICIT_OBJECTS.remove("headerValues");
    IMPLICIT_OBJECTS.remove("flowScope");

    // My own utility method
    IMPLICIT_OBJECTS.put("contextPath", CONTEXT_PATH);
}

@Override
public Object getValue(ELContext context,Object base, Object property)
        throws ELException {
    // variable resolution is a special case of property resolution
    // where the base is null.
    if (base != null) {
        return null;
    }
    if (property == null) {
        String message = MessageUtils.getExceptionMessageString
            (MessageUtils.NULL_PARAMETERS_ERROR_MESSAGE_ID, "property");
        throw new PropertyNotFoundException(message);
    }

    Integer index = IMPLICIT_OBJECTS.get(property.toString());

    if (index == null) {
        return null;
    } else {
        FacesContext facesContext = (FacesContext) context.getContext(FacesContext.class);
        ExternalContext extCtx = facesContext.getExternalContext();
            switch (index) {

            case COMPOSITE_COMPONENT:
                // The following five lines violate the specification.
                // The specification states that the 'cc' implicit object
                // always evaluates to the current composite component,
                // however, this isn't desirable behavior when passing
                // attributes between nested composite components, so we
                // need to alter the behavior so that the components behave
                // as the user would expect.
                /* BEGIN DEVIATION */
                CompositeComponentStackManager manager =
                      CompositeComponentStackManager.getManager(facesContext);
                Object o = manager.peek();
                /* END DEVIATION */
                if (o == null) {
                    o = UIComponent.getCurrentCompositeComponent(facesContext);
                }
                context.setPropertyResolved(o != null);
                return o;
            case PARAM:
                context.setPropertyResolved(true);
                return extCtx.getRequestParameterMap();
            case PARAM_VALUES:
                context.setPropertyResolved(true);
                return extCtx.getRequestParameterValuesMap();
            case CONTEXT_PATH:
                context.setPropertyResolved(true);
                return extCtx.getRequestContextPath();
            case RESOURCE:
                context.setPropertyResolved(true);
                return facesContext.getApplication().getResourceHandler();
            default:
                return null;
        }
    }
}

}

接下来,在 faces-config.xml 中,添加以下条目:

<application>
    <el-resolver>
        com.example.templates.jsf.CustomImplicitObjectELResolver
    </el-resolver>
</application>
于 2013-04-11T16:32:47.637 回答