在客户端或服务器端拦截 Grails GSP 操作
Intercepting Grails GSP actions on either client or server side
此处为 Grails 2.4.5。我正在尝试为我的 GSP 实现以下 UX 行为:
- 如果用户有权单击按钮,则他们可以这样做;然而
- 如果用户没有点击按钮的权限,那么当他们点击按钮时,屏幕顶部会出现一条横幅消息(闪烁?) rose/pinkish/red 背景说明“您无权执行此操作”
为了确定用户是否拥有所需的权限,我可以访问 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 -->
考虑到所有这些,我的问题是:How/where 我应该:(1) 响应“update
”按钮的点击处理程序,(2) 执行访问检查, (3) 呈现 error/banner/flash 消息? 代码示例(即使是伪代码)也很棒!
最好的方法是在用户无权使用按钮时隐藏该按钮。这可以通过 <sec:hasPermission permission="UPDATE_BUZZ">button</sec:hasPermission>
轻松实现
如果您希望即使未经许可的用户也能显示按钮,您可以使用相同的 hasPermission 向按钮添加额外的 class。现在使用 jQuery 捕获 class 的时钟事件并显示您的消息。
以下是我的建议:
- 确保您的控制器方法是基于角色的
- 取消 GSP 中的权限检查,如果按钮应该对所有人可见
- 提交后创建一个AJAX调用,如果响应状态为403,则显示横幅。
根据你的问题,我假设你不想刷新页面,甚至可能不想调用 ajax。因为如果你这样做了,那么展示横幅就不难了。您只希望它表现得像 JavaScript client-side 验证(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 按钮上创建一个包装器,这样您就可以在按钮上显示即时消息。
问题
- 如果用户在屏幕上时更改了用户权限怎么办? Ajax 会解决这个问题,但这不会。加载屏幕后,一切都已修复。
- 横幅与按钮一起
第二种解法
在布局顶部添加一个通用 div
以显示即显消息。然后创建一个类似于上面的标签。只是不要在呈现的模板中添加 flash 消息。像
<g:submitButton name="name" value="value" onclick="<unhide flash at top of layout if no permission>"/>
问题
- 如果用户在屏幕上时更改了权限怎么办?
不确定你为什么需要 onclick 处理程序,但如果没有理由只是 Aramiti 的解决方案。
如果我是你,我可能会尝试在这种情况下使用 before-action 过滤器。在此过滤器中,我将检查当前用户是否有权执行此类操作(检查权限应始终在 server-side 中完成,出于安全原因)并且:
如果安全检查通过 - 只是 return true(控制器将继续它的流程)
如果安全检查失败 - 您可以使用默认 flash.message 和 return false(使用适当的 css 样式闪现消息可能会出现在屏幕顶部具有 rose/pinkish/red 背景)
示例代码:
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
}
}
如果您只想对特定 controller/action 使用过滤器,请选中 applying section. Remember also, that you can use invert rule filter。
有关不同 filterTypes 的更多信息。
您还应该记得将 flash.message 部分添加到您的布局(或选定的视图)中。您始终可以指定 type of flash 消息,它是 css 样式。
此处为 Grails 2.4.5。我正在尝试为我的 GSP 实现以下 UX 行为:
- 如果用户有权单击按钮,则他们可以这样做;然而
- 如果用户没有点击按钮的权限,那么当他们点击按钮时,屏幕顶部会出现一条横幅消息(闪烁?) rose/pinkish/red 背景说明“您无权执行此操作”
为了确定用户是否拥有所需的权限,我可以访问 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 -->
考虑到所有这些,我的问题是:How/where 我应该:(1) 响应“update
”按钮的点击处理程序,(2) 执行访问检查, (3) 呈现 error/banner/flash 消息? 代码示例(即使是伪代码)也很棒!
最好的方法是在用户无权使用按钮时隐藏该按钮。这可以通过 <sec:hasPermission permission="UPDATE_BUZZ">button</sec:hasPermission>
如果您希望即使未经许可的用户也能显示按钮,您可以使用相同的 hasPermission 向按钮添加额外的 class。现在使用 jQuery 捕获 class 的时钟事件并显示您的消息。
以下是我的建议:
- 确保您的控制器方法是基于角色的
- 取消 GSP 中的权限检查,如果按钮应该对所有人可见
- 提交后创建一个AJAX调用,如果响应状态为403,则显示横幅。
根据你的问题,我假设你不想刷新页面,甚至可能不想调用 ajax。因为如果你这样做了,那么展示横幅就不难了。您只希望它表现得像 JavaScript client-side 验证(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 按钮上创建一个包装器,这样您就可以在按钮上显示即时消息。
问题
- 如果用户在屏幕上时更改了用户权限怎么办? Ajax 会解决这个问题,但这不会。加载屏幕后,一切都已修复。
- 横幅与按钮一起
第二种解法
在布局顶部添加一个通用 div
以显示即显消息。然后创建一个类似于上面的标签。只是不要在呈现的模板中添加 flash 消息。像
<g:submitButton name="name" value="value" onclick="<unhide flash at top of layout if no permission>"/>
问题
- 如果用户在屏幕上时更改了权限怎么办?
不确定你为什么需要 onclick 处理程序,但如果没有理由只是 Aramiti 的解决方案。
如果我是你,我可能会尝试在这种情况下使用 before-action 过滤器。在此过滤器中,我将检查当前用户是否有权执行此类操作(检查权限应始终在 server-side 中完成,出于安全原因)并且:
如果安全检查通过 - 只是 return true(控制器将继续它的流程)
如果安全检查失败 - 您可以使用默认 flash.message 和 return false(使用适当的 css 样式闪现消息可能会出现在屏幕顶部具有 rose/pinkish/red 背景)
示例代码:
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
}
}
如果您只想对特定 controller/action 使用过滤器,请选中 applying section. Remember also, that you can use invert rule filter。
有关不同 filterTypes 的更多信息。
您还应该记得将 flash.message 部分添加到您的布局(或选定的视图)中。您始终可以指定 type of flash 消息,它是 css 样式。