【问题标题】:jsf 2.0 return http error code after failed GET parameter validationjsf 2.0 在 GET 参数验证失败后返回 http 错误代码
【发布时间】:2011-09-05 09:07:05
【问题描述】:

我有这个本地网址: http://localhost:8084/Name/faces/Blah.xhtml?flkatid=AAA

这是来自 facelet 的片段,它检查参数“flkatid”并将其分配给 bean:

    <f:metadata>
        <f:viewParam name="flkatid"
                     id="flkatid"
                     value="#{floKatBean.flkatid}"
                     required="true"
                     requiredMessage="URL incomplete"
                     validator="#{floKatBean.validateFlKatId}"
                     validatorMessage="URL incomplete or invalid"
                     >
        </f:viewParam>
        <f:event type="preRenderView" listener="#{floKatBean.init}"/>
        <f:event type="preRenderView" listener="#{floBean.holFloListe}"/>
    </f:metadata>

floKatBean.flkatid 是整数,因此 URL 无效。显示一个页面,告诉您:

flkatid: 'AAA' 必须是由一位或多位数字组成的数字。 flkatid: 'AAA' 必须是介于 -2147483648 和 2147483647 之间的数字 例如:9346

JSF 检查参数本身,因为它知道 bean 元素是一个整数。仅当参数为整数时才调用自定义验证器。

是否可以让服务器返回一个 HTTP 错误代码,例如403(禁止)而不离开“标准 JSF 世界”(或切换到 RichFaces、MyFaces、SmileyFaces 或其他)?我在 f:viewParam 中找不到任何内容来“失败”页面。也许在其他地方?

【问题讨论】:

    标签: jsf facelets


    【解决方案1】:

    我发现最好的方法(处理请求参数和发送有用的 HTTP 响应)是完全删除 f:viewParams,并“手动”处理 preRenderView 监听器中的参数,例如这个:

    public void preRenderViewCheckParameters() throws IOException {
        if (!isPostback()) {
            flkatid = getFlkatidFromRequest();
            if (flkatid == null) {
                responseSendError(404, "URL incomplete or invalid!");
            }
        }
    }
    private Integer getFlkatidFromRequest(){
        try {
            return Integer.valueOf(getRequestParameter("flkatid"));
        } catch (NumberFormatException e) {
            return null;
        }
    }
    
    // util methods stolen from OmniFaces (check out this project, you'll love it):
    // https://github.com/omnifaces/omnifaces/blob/master/src/org/omnifaces/util/Faces.java
    public static String getRequestParameter(String name) {
        return FacesContext.getCurrentInstance().getExternalContext()
                           .getRequestParameterMap().get(name);
    }
    public static void responseSendError(int status, String message)
                               throws IOException {
        FacesContext facesContext = FacesContext.getCurrentInstance();
        facesContext.getExternalContext().responseSendError(status, message);
        facesContext.responseComplete();
    }
    

    然后,在视图中:

    <f:metadata>
        <f:event listener="#{portariasMB.preRenderViewLoadPortaria}"
                 type="preRenderView" />
    </f:metadata>
    

    也许代码多一点,但至少更简单。

    另外,这样做可以避免weird problems with messages not being displayed,所以...这就是我一直在做的事情。

    【讨论】:

    • 还可以。我只是不确定这如何解决当您转到 404 错误页面时没有显示面部消息的问题。
    • 是的,这个例子不会将消息排入队列,但是如果你使用addMessage 而不是responseSendError 它会起作用。在消息组件渲染后初始化的 bean 的 @PostConstruct 方法中,它不会。
    【解决方案2】:

    您可以在验证器中执行ExternalContext#responseSendError()。但这要求将值声明为 String 而不是 Integer 并删除 required="true",所有这些都是为了防止 JSF 默认验证机制进行 null/empty 检查以及从 String 转换为Integer.

    <f:metadata>
        <f:viewParam name="flkatid" value="#{floKatBean.flkatid}" 
            validator="#{floKatBean.validateFlKatId}" 
            validatorMessage="URL incomplete or invalid" 
        />
        ...
    </f:metadata>
    

    public void validate(FacesContext context, UIComponent component, Object value) 
        throws ValidatorException, IOException
    {
        if (value == null || !((String) value).matches("\\d+")) {
            context.getExternalContext().responseSendError(
                403, (String) component.getAttributes().get("validatorMessage"));
        }
    }
    

    您可以改为在 init() 方法中进行转换。

    this.flkatidInteger = Integer.valueOf(this.flatkid);
    

    【讨论】:

    • 我知道...在问这个问题之前,我成功地尝试了类似的东西。但我想将该值保持为整数,这是针对 SQL 注入的另一个额外保护级别。我更喜欢首先使用标准验证器,而我自己的只是一个额外的。一个人永远都不够偏执:-)
    • @BalusC 嗨,BalusC!我很好奇您对我的回答中提出的解决方案有何看法。我在JSF开发方面还很不成熟,很想知道你的意见! :)
    • 我想“public void validate”应该是“public void validateFlKatId”
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-22
    • 1970-01-01
    • 2011-05-25
    • 1970-01-01
    相关资源
    最近更新 更多