Grails 检查特定控制器操作的角色访问
Posted
技术标签:
【中文标题】Grails 检查特定控制器操作的角色访问【英文标题】:Grails check role access for specific controller action 【发布时间】:2014-08-24 07:25:24 【问题描述】:我需要根据用户是否可以访问(通过角色定义)特定控制器/操作来显示/隐藏操作按钮。我正在使用 Spring Security 插件。
我的目标是为每个控制器的每个方法使用注释 @Secured("ROLE_..."),我正在寻找一种方法来检查,在调用操作之前,如果用户有权访问这个具体的动作。我猜有办法检查这一点,因为注释带来了信息,但我找不到任何解决方案。
在这个例子中,我试图找到 HASACCESS 方法:
带有@Secured注解的控制器
class MyExampleController
@Secured("ROLE_ADMIN")
def myMethod() do stuff..
要包含链接的 html 代码
<role:link controller="myExample" action="myMethod">Action</role:link>
还有我的 tagLib 角色
class RoleTagLib
static namespace = "role"
def link = attrs, body ->
User user = (User) springSecurityService.currentUser
if(HASACCESS(user, attrs.controller, attrs.action))
out << g.link(attrs, body)
我在this thread 中找到了包含在 SecurityTagLib 中的“hasAccess()”方法,但该方法受到保护,即使我用我的扩展 SecurityTagLib,此方法的调用也会返回“没有方法签名...” .我认为它使用了 Config.groovy 中定义的 interceptUrlMap 而不是注释。
编辑:我成功扩展了安全 tagLib 并使用了“hasAccess”方法,但它似乎只使用了 Config.groovy 中包含的 interceptUrlMap,并不关心我放在控制器中的注释。
【问题讨论】:
【参考方案1】:使用
<sec:ifAllGranted roles="ROLE_ADMIN,ROLE_SUPERVISOR">
secure stuff here
</sec:ifAllGranted>
或
<sec:ifAnyGranted roles="ROLE_ADMIN,ROLE_SUPERVISOR">
secure stuff here
</sec:ifAnyGranted>
根据Spring Security Core Grails plugin documentation。
或者简单地将 Spring 安全核心标签库与您的标签库一起使用。
class RoleTagLib
static namespace = "role"
SpringSecurityService springSecurityService
def link = attrs, body ->
User user = (User) springSecurityService.currentUser
sec.ifAnyGranted(roles: 'ROLE_ADMIN,ROLE_SUPERVISOR')
out << g.link(attrs, body)
【讨论】:
是的,SecurityTagLib 带来了这种检查角色的方式,但我尝试找到一种更“集中”且更轻松的方式来调整我的 .gsp 文件。我不想为每个 g:link 标签都放置这些测试,我想简单地将 g:link 替换为我的角色:link。 啊,我明白了。那么你是否尝试过简单地包装spring security taglib? 是的,我已经尝试过(根据我在帖子中提到的另一个线程),但我无法成功。似乎安全 tagLib 中的“hasAccess”方法使用 Config.groovy 中定义的interceptUrlMap 而不是注释,因为 sec:ifAnyGranted 通过阻止访问来工作,而“hasAccess”方法授予访问它应该阻止......它会强制我逐个 URL 定义每个特定角色允许的每次访问。【参考方案2】:好的,我找到了解决方案。 SecurityTagLib 中的“hasAccess”方法基于 Config.groovy 中的 grails.plugins.springsecurity.securityConfigType。我的初始值是 SecurityConfigType.InterceptUrlMap 然后我会定义每个可访问的 url 并指定哪个角色可以在 grails.plugins.springsecurity.interceptUrlMap
解决办法是把它改成SecurityConfigType.Annotation,把interceptUrlMap修改成staticRules。然后方法“hasAccess”基于控制器中定义的注解,可以正确隐藏我的tagLib从SecurityTagLib包装的内容。
Config.groovy中有代码
grails.plugins.springsecurity.securityConfigType = SecurityConfigType.Annotation
grails.plugins.springsecurity.staticRules = [
... your rules ... for example:
'/**': ['ROLE_ADMIN_ACCESS']
]
我的tagLib的代码
class RoleTagLib extends SecurityTagLib
static namespace = "role"
def link = attrs, body ->
if (hasAccess(attrs.clone(), "link"))
out << g.link(attrs, body)
我使用它来显示或隐藏我的 .gsp 文件中的任何链接,基于为每个控制器的每个操作放置的 @Secured 注释
<role:link controller="myController" action="myAction">
Action
</role:link>
【讨论】:
如果你使用命名空间sec.
,那么你不需要扩展SecurityTagLib。 if (sec.hasAccess(attrs.clone(), "true")) ...
至少对我有用。此外,使用字符串 true
可以清楚地表明任何非空字符串都可以。【参考方案3】:
这适用于 Grails 2.3
要检查来自另一个控制器或服务的操作访问,请执行以下操作:
@Secured(["ONE_OF_MY_ROLES"])
class SomeController
SecurityTagLib securityTagLib = (SecurityTagLib)Holders.grailsApplication.mainContext.getBean('grails.plugins.springsecurity.SecurityTagLib')
def show()
def access = securityTagLib.hasAccess([controller: 'product', action: 'show'], 'access')
【讨论】:
以上是关于Grails 检查特定控制器操作的角色访问的主要内容,如果未能解决你的问题,请参考以下文章
Grails Spring Security UI、用户和角色管理访问