`
yuzhi2217
  • 浏览: 36578 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

JSF项目中实现基于RBAC模型的权限管理设计(二) 转

    博客分类:
  • JSF2
 
阅读更多

4.3 权限验证模块设计

一个好的权限管理机制在项目中应用时,最好不要让程序员在具体业务代码的方法中来判断用户权限。因为这意味着大量重复的代码。同时,也会导致权限机制的修改造成所有业务代码都需要修改一遍。

最好办法是实现与具体业务代码无关的独立的权限验证模块。这个模块可以拦截用户对资源的访问请求,并且在该请求被实施前做出权限判断,将权限不符的访问导向警告或提示页面。

 

       在普通的JSP项目中,我们往往会利用TomcatServlet filter机制来实现这样的功能,但filter机制的颗粒度不够,无法做到ACTION级别。另一个问题是,在JSF项目中,页面的跳转默认使用的是Forward形式,而不是redirect形式的URL重定向,因此Filter往往无法截获页面的转向。

 

       因此,在JSF项目中我们首先需要解决如何截获到用户对资源的访问的问题。

4.3.1 捕获URL级别的资源访问

JSF中,我们有时候会使用PhaseListener观察JSF生命周期,这给我们一个思路,通过PhaseListener 可以在一个点上(JSF生命周期的Restore View phase阶段)来获取请求和输出路径信息(这个路径实际上就是我们定义的URL类型的资源)。路径获取后我们就可以据此进行鉴权,从而避免在每个页面或者每个backing bean中判断用户访问权限,造成过多的冗余代码和管理上的混乱。

 

步骤一:在faces-config.xml中注册 自定义的PhaseListener

<lifecycle>      <phase-listener>com.laomao.view.listener.PermissionPhaseListener</phase-listener>

</lifecycle>

 

步骤二:实现我们自己的PhaseListener接口

package com.laomao.view.listener;

import javax.el.MethodExpression;

import javax.faces.FacesException;

import javax.faces.application.Application;

import javax.faces.application.NavigationHandler;

import javax.faces.context.FacesContext;

import javax.faces.event.PhaseEvent;

import javax.faces.event.PhaseId;

import javax.faces.event.PhaseListener;

import org.apache.commons.logging.Log;

import org.apache.commons.logging.LogFactory;

 

public class PermissionPhaseListener implements PhaseListener {

   

    private static Log log = LogFactory.getLog(PermissionPhaseListener.class);

   

    @Override

    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,如/noPermission.xhtml

            System.out.println("afterPhase: " + viewId);

           

            //判断用户的操作权限

            boolean isEnabled = true;

            //TODO: 鉴权代码

            //

           

            if(!isEnabled){

              gotoNoPermissionPage();

            }

        }

    }

   

    /**

     * 转入无权限声明页面

     * @param expression

     */

    private void gotoNoPermissionPage() {

        FacesContext context = FacesContext.getCurrentInstance();

        Application application = context.getApplication();

               

        NavigationHandler navHandler = application.getNavigationHandler();

        navHandler.handleNavigation(context, null, Constants.NAVIGATION_NO_PERMISSION);

        context.renderResponse();

    }

}

 

 

         PhaseListener可以捕获到URL的变化,对于页面内部的操作则无能为力了。例如CommandButton的操作,可能删除了一条记录,但URL却没有变化,仅仅是页面局部进行了刷新。因此,我们还需要一个可以捕获到用户对ACTION类型的资源的访问的利器。这个利器就是ActionListener

4.3.2 捕获ACTION级别的资源访问

当一个按钮被按下,或者命令联结被点击时,JSF会在invork application阶段的broadcast

event时通过ActionListener调用事先绑定的事件处理方法。如果有用户自定义的ActionListener时,JSF将使用用户自定义ActionListener来代替默认的ActionListener

 

用户自定义ActionListener必须实现javax.faces.event.ActionListener接口,并实现其接口方法:public void processAction(ActionEvent actionEvent)

 

注意,在这个实现方法里,必须调用控件的事件处理方法(JSF Backing Bean中的事件处理方法),并对其返回值做出画面迁移处理和其他你自己的处理等。

 

步骤一:在faces-config.xml中注册 自定义的ActionListener

<application>       <action-listener>com.laomao.view.listener.ActionListenerImpl</action-listener>

</application>

 

步骤二:实现我们自己的ActionListener接口

package com.laomao.view.listener;

import javax.el.ELContext;

import javax.el.MethodExpression;

import javax.faces.FacesException;

import javax.faces.application.Application;

import javax.faces.application.NavigationHandler;

import javax.faces.component.ActionSource2;

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;

 

public class ActionListenerImpl implements ActionListener {

       private static Log log = LogFactory.getLog(PermissionPhaseListener.class);

      

       @Override

       public void processAction(ActionEvent actionEvent) throws AbortProcessingException {

              FacesContext facesContext = FacesContext.getCurrentInstance();

        Application application = facesContext.getApplication();

 

        ActionSource2 actionSource = (ActionSource2)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);

                //fromActionfaces-config.xml中登记的是一致的

                //fromAction: #{loginController.loginAction} outcome: success

                System.out.println("fromAction: " + fromAction + ", outcome: " + outcome);

               

                boolean isEnabled = true;

                //TODO: 鉴权代码

                 //

                if(!isEnabled){

                       //如果无此权限,转到权限不足页面

                       gotoNoPermissionPage(actionSource.getActionExpression());

                }

               

            }

            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();

 

       }

      

       /**

        * 转入无权限声明页面

        * @param expression

        */

       private void gotoNoPermissionPage(MethodExpression expression) {

        FacesContext context = FacesContext.getCurrentInstance();

        Application application = context.getApplication();

               

        NavigationHandler navHandler = application.getNavigationHandler();

        navHandler.handleNavigation(context, null == expression ? null : expression.getExpressionString(), Constants.NAVIGATION_NO_PERMISSION);

        context.renderResponse();

    }

 

}

 

转:http://laomaowww.blog.163.com/blog/static/16600567320124751827427/

分享到:
评论

相关推荐

    一个完整的权限管理系统

    压缩包中的"rbac"可能是指Role-Based Access Control(基于角色的访问控制)的缩写,这是权限管理系统的核心机制。RBCA允许管理员将权限分配给特定的角色,而不是单独的用户。用户通过加入不同的角色来获取相应的...

    基于JavaWeb的课程设计管理系统源代码,JSP+MySQL实现

    本项目是基于JavaWeb技术的课程设计管理系统源代码,采用了JSP(Java Server Pages)作为前端展示技术,与后端MySQL数据库相结合,实现了一个完整的系统。这样的系统设计模式通常用于构建动态、交互式的Web应用程序...

    javaEE实现健康管理系统.rar

    这通常通过JavaEE的内置安全机制实现,如使用JAAS(Java Authentication and Authorization Service)进行身份验证,以及角色基的访问控制(RBAC)来管理用户权限。在数据库中,可能有用户表存储用户名、密码(经过...

    JSP班级管理系统_class毕业设计—(包含完整源码可运行).rar

    这可能通过实现角色-权限(RBAC)模型来实现。 8. **文件上传与下载**:系统可能支持上传学生的作业或教学资料,这就需要处理文件上传和下载的功能,可能涉及到对文件路径的管理以及安全的文件访问控制。 9. **报表...

    基于javaweb+jsp的酒店订单管理系统(hibernate+xml)

    7. **安全与权限管理**: 系统可能还包括用户认证和授权机制,如使用session和cookie管理用户登录状态,以及基于角色的访问控制(RBAC)来限制不同用户对系统资源的访问。 8. **异常处理与日志记录**: 异常处理是...

    tomahawk20-1.1.11-bin.zip

    标题中的"tomahawk20-1.1.11-bin.zip"是一个软件包,它很可能包含Tomahawk项目的特定版本(1.1.11)的二进制文件。Tomahawk通常指的是Apache MyFaces Tomahawk项目,这是一个开源JavaServer Faces (JSF)组件库,提供...

    javaweb项目16-20

    9. **安全与认证**:实现用户登录和权限控制,如使用HTTPS、CSRF防护、基于角色的访问控制(RBAC)等。 10. **部署与调试**:学习如何在Tomcat、Jetty等应用服务器上部署Web应用,以及使用IDE进行调试。 通过这些...

    j2ee web端知识及案例

    实际项目中,J2EE Web应用可能涉及网上商城、社交平台、企业管理系统等多种类型。学习如何结合上述技术解决具体问题,如用户注册登录、商品展示、订单处理、权限控制等,是提升实战能力的关键。 综上所述,J2EE Web...

    三级菜单后台系统ui框架模板

    4. **权限控制**:后台系统往往需要权限管理,如角色、权限分配,可能采用了RBAC(Role-Based Access Control)模型。这部分可以通过Spring Security或Apache Shiro等框架实现。 5. **响应式设计**:为了适应不同...

    J2ee网上商城项目

    - 授权:使用角色基础的访问控制(RBAC),限制不同用户组的权限。 - 加密:对敏感信息如密码进行哈希加密,保护用户隐私。 5. **购物车与订单系统** 购物车模块使用Session对象存储临时的商品选择,而订单系统...

    JBoss7-配置管理员手册

    - JBoss 7的配置涉及到网络、安全管理、资源管理等多个方面,理解并熟练掌握这些配置是实现高效运维的关键。 - 通过深入学习和实践,管理员能够充分利用JBoss 7的特性,构建健壮、可扩展的企业级应用环境。 本...

    spring应用开发完全手册(10-11)

    2. 权限授权:在用户认证的基础上,本章会讨论如何对不同用户角色分配不同的操作权限,实现基于角色的访问控制(RBAC)。这包括URL级别的权限控制和业务对象级别的细粒度授权。 3. 用户注册和管理:涵盖用户注册...

    Shiro1.3.2 source

    3. **Access Control**: Shiro提供了多种访问控制策略,如基于角色的访问控制(RBAC)和基于权限的访问控制(PBAC)。 在Shiro中,开发者可以通过注解、配置文件或代码动态地进行权限设置。 **三、会话管理...

    北大青鸟6.0Y2课件,使用Java企业级技术开发大型系统(5)

    4. **数据库设计与管理**:在大型系统开发中,数据库的设计和管理至关重要。课程可能会涵盖SQL语言、数据库优化、事务处理和并发控制等内容,确保学员能有效地存储和检索大量数据。 5. **安全性**:学习者会接触到...

    Java EE的多层软件体系架构安全研究.zip

    Java EE中的安全上下文(Security Context)用于存储用户的权限信息,通过定义角色并映射到特定的资源,实现对资源的访问控制。 二、Servlet和JSP安全 1. Servlet Filter:Filter 是Java EE中用于拦截请求的组件,...

    第一个EJB工程....

    10. **安全性**:EJB提供了基于角色的访问控制(RBAC),可以限制不同用户对EJB的访问权限。 在"教师系统"这个作业中,你可能会创建一个会话Bean来表示教师服务,提供添加、修改课程等功能。CourseManage可能是这个...

    netctoss系统

    6. **权限设置**:从"权限设置.JPG"推测,系统有完善的权限管理机制,可能使用角色基础的访问控制(RBAC),确保不同用户和角色只能访问其授权的资源。 7. **日志与监控**:对于这样的关键业务系统,日志记录和性能...

    jboss portal手册

    它支持多种安全模型,如基于角色的访问控制(RBAC)、LDAP集成等,确保只有授权的用户才能访问特定的portlet和资源。 **5. 部署与管理** JBoss Portal提供了丰富的管理工具,包括控制台和API,用于部署、监控和管理...

Global site tag (gtag.js) - Google Analytics