根据用户权限隐藏/禁用GUI元素的最佳方法是什么?

时间:2011-04-18 09:24:39

标签: design-patterns gwt user-interface extjs

我正在启动一个Web应用程序,客户端在纯ExtJS中实现,在Grails中实现中间层。该应用程序具有基于角色的授权,用户可以拥有许多细粒度的角色,如SOME_FORM_READ,SOME_FORM_UPDATE,SOME_DATA_DELETE,SOME_DATA_READ等。根据用户的角色,某些GUI元素需要被禁用或隐藏,而其他需要处于只读模式。

我在网上做了一些搜索,但没有发现任何专门解决这个问题的设计模式,所以我想出了自己的设计。我相信很多网络应用程序都会有类似的要求,所以我想在这里发布我的设计并听取人们的意见。我的设计绝不是一个完美的设计,但我希望它可以通过每个人的输入得到改善。虽然我正在使用ExtJS,但一般设计也应该适用于类似的框架,如GWT,Flex,Swing等。

所以,在这里:

我们需要在客户端层面处理有关授权的四种类型的代码(或信息):

  1. GUI元素操作代码,例如:

    panel.hide() form.setReadOnly(真)

  2. GUI元素权限要求,例如:

    form.requires('READ','FORM_READ_ROLE')

    adminPanel.requires( 'ADMIN_ROLE')

  3. 用户权限信息,基本上是用户拥有的角色列表;

  4. 授权逻辑:根据用户权限确定要隐藏/禁用的元素;

  5. 设计的核心是一个名为GUIPermissionManager的单例,简称GPM。这是一种集中式设计,因为大多数代码都在GPM中,因此GUI元素不会受到授权代码的污染。这就是GPM的工作原理:

    • GUI元素(需要某些访问权限)通过GPM注册其权限信息,如下所示:

      GPM.register(this,'DEPARTMENT_DELETE_ROLE'); //删除部门的按钮

    • GPM维护GUI权限注册列表

    • 在用户登录时,GPM会收到已分配使用的角色列表

    • GPM遍历GUI权限注册列表并根据用户权限确定要隐藏的GUI部分,然后相应地调用element.hide()

    问题

    • GUI元素以树形层次结构组织,例如面板包含一个按钮栏和一个表单,因此当隐藏面板时,无需进一步检查按钮栏和表单是否需要隐藏。 问题:如何在GPM中注册和维护此分层信息?
    • 目前,我只能想到GUI元素的两个用例:隐藏元素或将元素设置为只读(例如表单)。还有其他用例吗?
    • 在ExtJS中,为了隐藏元素,我们调用hide(),但是为了将表单设置为只读,我们必须提出自己的函数,假设它叫做setReadOnly(),如何让GPM知道哪个打电话的功能?将该功能作为注册的一部分传递?
    • 将表单设置为只读的最佳方法是什么?如果我使用setReadOnly()函数扩展表单组件,将会有很多代码重复,我必须为每个需要权限控制的表单执行此操作。是否可以在GPM中创建动态表单转换器,以便在表单设置为只读时,它会自动将所有可编辑字段替换为仅显示字段?

2 个答案:

答案 0 :(得分:6)

Q1:分层UI元素隐藏 - 优化您的GPM以避免隐藏已经通过父级隐藏的元素在我看来不会有太大的性能提升。我的理由:

  1. 您在用户登录时加载一次权限,而非所有时间。
  2. 根据编码的方式,无论如何都需要额外的处理来确定层次结构。
  3. 通过充分的规划,您可以避免注册数十个和数十个组件,并坚持使用总体容器。
  4. 如果您真的想要跟踪分层信息,您可以始终使用所有容器组件提供的'contains'方法来检查DisplayObject是否包含在其子列表中的任何位置(包括链中)。每次注册一个组件时都可以调用它来检查它是否已经注册了父组件。

    然后可以在字典中设置标志以忽略隐藏在该组件上。在迭代注册组件列表时,可以首先检查此标志,以确定应隐藏的内容。字典可以使用与注册组件的UID相对应的键。此外,当忽略其他GPM功能时,可以使用此标志忽略该组件,例如表单禁用(因为表单永远不会被看到)。

    Q2。在我的头顶,你可以禁用/启用组件,实现状态更改,或拦截事件,以及所有警报。这是一个非常广泛的问题,因为任何事情都可以完成 - 真的取决于设计师。

    Q3。你可以:

    1. 在注册组件时提供参数,例如指示它们的类型(用于隐藏的容器,用于设置为只读的表单等)。
    2. 检查每个组件是否已注册,以确定将要执行的操作。
    3. 您实际上将与各种组件建立合同,其中GPM知道其接口并相应地与它们进行交互。

      Q4。您始终可以将表单设置为禁用(启用= false)。这可以防止任何用户交互。某些外观将更改以指示组件已禁用,因此您可能需要修改其外观以防止某些此类显示行为。在该行上,您还可以更改其外观以隐藏某些元素,例如TextInput框的边框,以使其看起来更像是“视图”而不是禁用的输入。

      可以创建一个“变换器”来改变TextInputs和RichText组件等。这将花费大量的工作,并且可能应该构建到扩展的Form类而不是GPM中。我认为每个组件类型的不同皮肤状态可能是更好的解决方案,以避免创建和销毁组件只是为了改变表单的显示方式。

答案 1 :(得分:1)

小心谨慎!用户权限/授权应该在服务器端控制,而不是在客户端,尤其是基于js的webapps。它的安全风险很大。你应该在你的框架中考虑这一点。

编辑 - 您的客户端身份验证/私有管理框架是什么?这将主要指导您的客户端GUI管理。