JSF的权限设计

角色受限采访URL。
    由于JSF的流程在Servlet Filter之后, 所以不能使用Filter的层面获取到JSF的一些请求路径信息,即javax.faces.context.FacesContext.getCurrentInstance()应该是空的。
    这里可以使用javax.faces.event.PhaseListener来获取请求和输出路径信息。在face-config.xml配置好即可获取到请求和输出的页面路径。例如,用户当前处于公用页面A.jsf, 现在按链接想跳转到B.jsf; JSF首先会恢复A.jsf的视图,这时PhaseListener,验证合法就输出视图到B.jsf, 这时又会来到PhaseListener 恢复视图B.jsf, 可以将鉴权的代码添加到或BeforeParse, AfterParse方法里。
    ParseListener对h:outputLink或CommandLink是应该是可行的,因为只是对链接进行限制。 如果对于CommandButton可能是不行的,例如A.jsf 点击按钮action="#{bBean.bAction}",
    public String bAction() ...{
        //能够进入到方法内部,如果这里是很多逻辑操作,数据操作的话。。。。
        return "B_JSF";
        //只有在return之后ParseListener才能限制鉴权,那就晚了。而链接就不同,因为它没什么逻辑操作。
    }

    这种鉴权就要用到下面提到的第二种方法。

package web;

import java.io.IOException;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.event.PhaseEvent;
import javax.faces.event.PhaseId;
import javax.faces.event.PhaseListener;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/** *//**
* @author zealvampire
* @version 1.0  2006-10-17
*/
public class SecurityPhaseListener implements PhaseListener ...{

    private static final long serialVersionUID = 6186106530012195240L;
  
    private static final Log log = LogFactory.getLog(SecurityPhaseListener.class);


    /**//* (non-Javadoc)
     * @see javax.faces.event.PhaseListener#afterPhase(javax.faces.event.PhaseEvent)
     */
    public void afterPhase(PhaseEvent event) ...{
      
        PhaseId phaseId = event.getPhaseId();
        if (phaseId == PhaseId.RESTORE_VIEW || phaseId == PhaseId.INVOKE_APPLICATION) ...{
            FacesContext currentContext = FacesContext.getCurrentInstance();
            String viewId= currentContext.getViewRoot().getViewId();
            //ViewId 就是我们需要的路径,类似URL
    }

    /**//* (non-Javadoc)
     * @see javax.faces.event.PhaseListener#beforePhase(javax.faces.event.PhaseEvent)
     */
    public void beforePhase(PhaseEvent event) ...{
    }

    /** *//**
     *  (non-Javadoc)
     * @see javax.faces.event.PhaseListener#getPhaseId()
     */
    public PhaseId getPhaseId() ...{
        return PhaseId.ANY_PHASE;
    }

}

face-config.xml
<faces-config>
    <lifecycle>
        <phase-listener>
           web.SecurityPhaseListener
        </phase-listener>
    </lifecycle>
</face-config>


2. 扑获JSF中用户要执行的Action
    例子,用户在A.jsf点击CommandButton action="#{bBean.bAction}" 要是我们能在这个动作执行之前扑获到它并进行鉴权的话, 那就Sofu了。
    这个我是看Myfaces源码以及看face-config.xml格式看到的, 里面有个ActionListener, 猜猜是什么东西? 是的,就像写Swing一样,用来处理消息和动作的。先看看Myfaces的默认实现。
/**//*
* Copyright 2004 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.myfaces.application;

import javax.faces.FacesException;
import javax.faces.application.Application;
import javax.faces.application.NavigationHandler;
import javax.faces.component.ActionSource;
import javax.faces.context.FacesContext;
import javax.faces.el.EvaluationException;
import javax.faces.el.MethodBinding;
import javax.faces.event.AbortProcessingException;
import javax.faces.event.ActionEvent;
import javax.faces.event.ActionListener;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;


/** *//**
* @author Manfred Geiler (latest modification by $Author: mbr $)
* @author Anton Koinov
* @version $Revision: 231425 $ $Date: 2005-08-11 07:49:45 -0400 (Thu, 11 Aug 2005) $
*/
public class ActionListenerImpl
    implements ActionListener
...{
    private static final Log log = LogFactory.getLog(ActionListenerImpl.class);

    public void processAction(ActionEvent actionEvent) throws AbortProcessingException
    ...{
        FacesContext facesContext = FacesContext.getCurrentInstance();
        Application application = facesContext.getApplication();

        ActionSource actionSource = (ActionSource)actionEvent.getComponent();
        MethodBinding methodBinding = actionSource.getAction();

        String fromAction;
        String outcome;
        if (methodBinding == null)
        ...{
            fromAction = null;
            outcome = null;
        }
        else
        ...{
            fromAction = methodBinding.getExpressionString();
            try
            ...{
                outcome = (String) methodBinding.invoke(facesContext, null);
            }
            catch (EvaluationException e)
            ...{
                Throwable cause = e.getCause();
                if (cause != null && cause instanceof AbortProcessingException)
                ...{
                    throw (AbortProcessingException)cause;
                }
                else
                ...{
                    throw new FacesException("Error calling action method of component with id " + actionEvent.getComponent().getClientId(facesContext), e);
                }
            }
            catch (RuntimeException e)
            ...{
                throw new FacesException("Error calling action method of component with id " + actionEvent.getComponent().getClientId(facesContext), e);
            }
        }

        NavigationHandler navigationHandler = application.getNavigationHandler();
        navigationHandler.handleNavigation(facesContext,
                                           fromAction,
                                           outcome);
        //Render Response if needed
        facesContext.renderResponse();

    }
}

    看到fromAction = methodBinding.getExpressionString();这个你就偷笑了吧,那确实,这个就是我们要的bBean.bAction 模仿这个类重新写一个类吧,。然后在face-config.xml配置一下。
  
<application>
        <variable-resolver>
            org.springframework.web.jsf.DelegatingVariableResolver
        </variable-resolver>
        <action-listener>OurOwnActionListenerImpl</action-listener>
    </application>

    ActionListener是一个接口,我想在其他JSF的实现,应该也是通过的吧。

你可能感兴趣的:(apache,xml,Web,servlet,JSF)