使用 PhaseListener 而不是 Servlet Filter 进行授权的限制

Limitations of using a PhaseListener instead of a Servlet Filter for authorization

我目前正在使用如下的 PhaseListener 来执行用户授权。

private PhaseId phaseId = PhaseId.RESTORE_VIEW;

@Override
public void afterPhase(PhaseEvent event) {

    FacesContext fc = event.getFacesContext();
    boolean isOnAllowedPage = false;
    String[] allowedPages = choseRightPages(); // chose pages for role

    for (String s : allowedPages) {
        if (fc.getViewRoot().getViewId().lastIndexOf(s) > -1) {
            isOnAllowedPage = true;
            break;
        }
    }

    if (!isOnAllowedPage) {
        NavigationHandler nh = fc.getApplication().getNavigationHandler();
        nh.handleNavigation(fc, null, "prohibited");
    }
}

它可以满足我的要求,但是我没有看到它被列在 How to handle authentication/authorization with users in a database? and this Coderanch topic titled "authorization with phaselistener problem" 中还提到了以下内容:

You shouldn't couple authorization that tight with JSF. Better make use of container managed authentication and/or a simple filter acting on an url-pattern covering the protected pages.

我不完全理解在执行用户授权时使用 PhaseListener 而不是 Filter 的限制。有人可以给我解释一下吗?

A PhaseListener 仅在 JSF 请求(即调用 FacesServlet 的 HTTP 请求)上触发。当执行非 JSF 请求时它不会被触发,因此暴露了非 JSF 请求的潜在安全漏洞。无论目标 servlet 是什么,都可以在每个 HTTP 请求上触发 servlet Filter

换句话说:HTTP 请求授权不应与 FacesContext 可用相关联,而应与 ServletRequest 可用相关联。始终尽可能尝试授权 "low level"。