Controle de acesso a componentes JSF com Phase Listener

Oi, este é meu primeiro post.

Estou aprendendo JSF 2.0 e estou desenvolvendo um controle de acesso que restrinja acesso tanto as páginas quanto aos componentes visuais. Um dos requisitos é que o desenvolvedor não tenha que configurar as regras de acesso nas páginas. As permissões serão baseadas nos ids dos componentes.

Construí um Phase Listener para interceptar a fase “Restore View” e dentro do método afterPhase estou colocando a lógica de autenticação (verificar se usuário está logado) e autorização (verificar se o usuário pode ver a página e setar o atributo rendered como false para os componentes aos quais ele não tiver acesso).

        if (sa.canUserAccessPage(userId, reqPageName)){

            for(UIComponent component : fc.getViewRoot().getChildren()){

                if (!sa.canUserAccessComponent(userId, reqPageName, component.getId())){
                    setInvisible(component);
                }

            }

O problema é que quando chamo fc.getViewRoot().getChildren(), a lista resultante possui apenas um componente do tipo UIInstructions.
O toString desse componente é: <?xml version='1.0' encoding='UTF-8' ?>.

A página que estou tentando acessar é:

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html">
    
    <h:head>
        <title>Protected Page</title>
    </h:head>

    <h:body>
        <h:outputText id="txb_msg1" value="Protected message one." title="Msg one"/> <br/><br/>
        <h:outputText id="txb_msg2" value="Protected message two." title="Msg two"/>  <br/><br/>
        <h:button id="btn_one" value="Button one" title="Button one"/>
    </h:body>

</html>

O que estou errando? Em qual fase do ciclo de vida posso ter acesso a todos os componentes de uma página?

Resolvi esse problema implementando um decorator para ViewHandler.

O framework JSF (2.0) facilita muito nosso trabalho ao disponibilizar uma classe wrapper.
Basta extendê-la e sobrcescever os métodos que devem ser decorados, no meu caso apenas o renderView.

Decorator

public class MyViewHandler extends ViewHandlerWrapper{
    private ViewHandler defaultViewHandler = null;

    public MyViewHandler() {
    }

    public MyViewHandler(ViewHandler defaultViewHandler) {
        super();
        this.defaultViewHandler = defaultViewHandler;
    }

    @Override
    public void renderView(FacesContext context, UIViewRoot viewToRender) throws IOException, FacesException {
         viewToRender.visitTree(VisitContext.createVisitContext(context),
            new VisitCallback() {

                @Override
                public VisitResult visit(VisitContext context, UIComponent target) {

                    // Authorization logic here
                    //    target.setRendered(false);
                    }
                    return VisitResult.ACCEPT;
                }

        });

        defaultViewHandler.renderView(context, viewToRender);
    }

    @Override
    public ViewHandler getWrapped() {
        return defaultViewHandler;
    }

Depois precisamos declarar o novo ViewHandler no faces-config.xml

    <application>
        <view-handler>org.something.MyViewHandler</view-handler>
    </application>

Pronto. A classe wrapper já se encarrega de chamar todos os métodos do antigo ViewHandler que não foram sobrescritos.

E como se obtem o Id dos components no decorator do view handler?

Pra mim só volta _viewRoot para todos os components. E getChildCount() destes volta 0.

Olá, boa tarde

Estou com o mesmo problema, conseguiu resolver?