分享

JSF的权限设计

 chanvy 2009-01-08

1. 角色受限采访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./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的实现,应该也是通过的吧。

3。 如果还有其他好的方案请和我们分享。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多