问题 在客户端或服务器端拦截Grails GSP操作


Grails 2.4.5在这里。我正在尝试为我的GSP实现以下UX行为:

  • 如果用户有权点击按钮,那么他们可以这样做;然而
  • 如果是用户  有权点击按钮,然后当他们点击按钮时,屏幕顶部会出现一条横幅消息(闪烁?),背景为玫瑰/粉红色/红色背景您无权执行此操作

要确定用户是否具有所需权限,我可以访问Groovy和GSP / taglib层的功能。

从Groovy / controller层:

SecurityUtils.hasPermission(String permission)
Ex: SecurityUtils.hasPermission('UPDATE_BUZZ')

从GSP / taglib层:

<sec:hasPermission permission="<permission name>">???</sec:hasPermission>
Ex: <sec:hasPermission permission="UPDATE_BUZZ">???</sec:hasPermission>

因此,给定这两种可用的访问检查机制,并给出以下控制器:

class FizzController {
    BuzzService BuzzService

    def buzz() {
        SomeData dataModel = buzzService.getModel(params)
        render(view: 'buzz', model: [ dataModel: dataModel ])
    }
}

...哪里 buzz.gsp 是:

<!-- Lots of HTML/GSP here -->
<g:submitButton name="update" value="Update" />
<!-- Lots more HTML/GSP down here -->

鉴于这一切,我的问题是: 我应该如何/在哪里:(1)回应'update'按钮的点击处理程序,(2)执行访问检查,以及(3)呈现错误/横幅/ flash消息? 代码示例(甚至伪代码)将是最棒的!


7925
2018-01-18 10:00


起源



答案:


我假设您不想刷新页面,甚至不需要ajax调用。因为如果你这样做,那么展示横幅并不困难。您只是希望它的行为类似于JavaScript客户端验证(明智的UX)。如果这个假设是错误的,那么请不要阅读并使用Aramiti的解决方案。否则继续。

第一解决方案

您可以创建一个以权限作为输入的标记。就像是

<myTagLib:flashOnNoPermission permission="PERM" name="name" value="value">
</myTagLib:flashOnNoPermission>

此标记的定义可以使用检查权限 sec:hasPermission。然后这个标签可以只渲染一个包含这样的东西的模板

<hidden flash message>
<g:submitButton name="name" value="value" onclick="<unhide flash if no permission>"/>

基本上在grails按钮上创建一个包装器,以便您可以使用flash按钮和按钮。

问题

  • 如果用户在屏幕上时更改了用户的权限,该怎么办? Ajax负责这一点,但事实并非如此。加载屏幕后,一切都已修复。
  • 横幅与按钮一起

二解决方案

添加一个共同的 div 在您的布局顶部显示Flash消息。然后创建一个类似于上面的标签。只是不要在渲染模板中添加flash消息。就像是

    <g:submitButton name="name" value="value" onclick="<unhide flash at top of layout if no permission>"/>

问题

  • 如果用户在屏幕上的权限发生了变化怎么办?

不知道为什么你需要东西onclick处理程序,但如果没有理由只是Aramiti的解决方案。


2
2018-01-22 16:14





以下是我的建议:

  1. 确保您的控制器方法是基于角色的
  2. 如果每个人都可以看到按钮,请删除GSP中的权限检查
  3. 提交时创建AJAX调用,如果响应状态为403,则显示横幅。

3
2018-01-21 18:09



投票可能对投票有价值。 - Armaiti
这是最好的解决方案。必须在模型验证期间在服务器端进行权限检查。使用Grails返回403状态并不是必需的,您只能返回消息源字符串(而不是JSON),对于主干模型,它将被视为save()上的错误。在客户端,你也可以捕获所有403和500,并使用类似toastr.error(消息)的smth。因此,将grails验证错误传递给客户端服务非常容易。 - Alex Shwarc
我宁愿做过滤。它似乎更清洁和通用的解决方案。 - Michal_Szulc


答案:


我假设您不想刷新页面,甚至不需要ajax调用。因为如果你这样做,那么展示横幅并不困难。您只是希望它的行为类似于JavaScript客户端验证(明智的UX)。如果这个假设是错误的,那么请不要阅读并使用Aramiti的解决方案。否则继续。

第一解决方案

您可以创建一个以权限作为输入的标记。就像是

<myTagLib:flashOnNoPermission permission="PERM" name="name" value="value">
</myTagLib:flashOnNoPermission>

此标记的定义可以使用检查权限 sec:hasPermission。然后这个标签可以只渲染一个包含这样的东西的模板

<hidden flash message>
<g:submitButton name="name" value="value" onclick="<unhide flash if no permission>"/>

基本上在grails按钮上创建一个包装器,以便您可以使用flash按钮和按钮。

问题

  • 如果用户在屏幕上时更改了用户的权限,该怎么办? Ajax负责这一点,但事实并非如此。加载屏幕后,一切都已修复。
  • 横幅与按钮一起

二解决方案

添加一个共同的 div 在您的布局顶部显示Flash消息。然后创建一个类似于上面的标签。只是不要在渲染模板中添加flash消息。就像是

    <g:submitButton name="name" value="value" onclick="<unhide flash at top of layout if no permission>"/>

问题

  • 如果用户在屏幕上的权限发生了变化怎么办?

不知道为什么你需要东西onclick处理程序,但如果没有理由只是Aramiti的解决方案。


2
2018-01-22 16:14





以下是我的建议:

  1. 确保您的控制器方法是基于角色的
  2. 如果每个人都可以看到按钮,请删除GSP中的权限检查
  3. 提交时创建AJAX调用,如果响应状态为403,则显示横幅。

3
2018-01-21 18:09



投票可能对投票有价值。 - Armaiti
这是最好的解决方案。必须在模型验证期间在服务器端进行权限检查。使用Grails返回403状态并不是必需的,您只能返回消息源字符串(而不是JSON),对于主干模型,它将被视为save()上的错误。在客户端,你也可以捕获所有403和500,并使用类似toastr.error(消息)的smth。因此,将grails验证错误传递给客户端服务非常容易。 - Alex Shwarc
我宁愿做过滤。它似乎更清洁和通用的解决方案。 - Michal_Szulc


如果我是你,我可能会尝试在这种情况下使用前置过滤器。在这个过滤器中,我会检查当前用户是否有权执行此类操作(由于安全原因,检查权限应始终在服务器端完成) 然后:

  • 如果安全检查通过 - 只返回true(控制器将继续它的流程)

  • 如果安全检查失败 - 您可以使用默认的flash.message并返回false(屏幕顶部可能会出现具有玫瑰色/粉红色/红色背景的有效css样式的闪烁消息)

示例代码:

class UserFilters {
   def filters = {
      // ... other filters ...
      permissionAllCheck(controller: '*', action: '*') {
         before = {
            doPermissionCheck(delegate)
         }
      }
   }

   private boolean doPermissionCheck(filters) {
         if (! YourService.checkForPermissionForCurrentlyLoggedUser()) {
            filters.flash.message = "You don't have permission to take this action"
            return false
         }
      true
   }
}

如果要仅对特定控制器/操作使用过滤器,请检查 应用 部分。还要记住,你可以使用 反转规则过滤器

有关不同的更多信息 filterTypes

您还应该记住将flash.message部分添加到布局(或选定的视图)。你总是可以指定 闪光类型 消息和它的CSS风格。


3
2018-01-23 05:27





最好的方法是在用户无权使用按钮时隐藏按钮。这很容易实现 <sec:hasPermission permission="UPDATE_BUZZ">button</sec:hasPermission>

如果您希望在未经许可的情况下为用户显示按钮,则可以使用相同的hasPermission向按钮添加额外的类。现在使用jQuery捕获该类的clock事件并显示您的消息。


2
2018-01-18 12:11



谢谢@ashipj(+1) - 是的,不幸的是我仍然需要向用户显示按钮, 甚至 如果他们没有权限点击+执行它。 您是否介意使用一些代码/伪代码示例更新您的答案,具体如下:(1)将额外的类添加到按钮中,以及(2)捕获该类的“时钟事件”? 我出于某种原因只是不理解......再次感谢! - smeeb