【发布时间】:2011-01-19 08:58:37
【问题描述】:
我目前正在为我的应用程序开发一个菜单,该菜单应该能够仅显示当前用户可以访问的控制器(在数据库中定义的请求图)。
如何检查当前用户是否有权访问特定的控制器和操作?
【问题讨论】:
我目前正在为我的应用程序开发一个菜单,该菜单应该能够仅显示当前用户可以访问的控制器(在数据库中定义的请求图)。
如何检查当前用户是否有权访问特定的控制器和操作?
【问题讨论】:
不确定最初提出此问题时的情况,但现在您可以使用 SpringSecurityUtils.ifAllGranted() 检查用户是否处于特定角色中,该字符串采用逗号分隔的角色列表。如果当前用户属于所有用户,则返回true。
if(SpringSecurityUtils.ifAllGranted('ROLE_ADMIN,ROLE_USER')) {
显然,如果您只需要一个角色,您可以简单地将其传递给函数。 SpringSecurityUtils 也有 ifAnyGranted、ifNotGranted 等方法,所以它应该适用于你想要完成的任何事情。
SpringSecurityUtils 是一个静态 API,因此您无需创建名为 springSecurityUtils 或类似名称的私有成员。
【讨论】:
查看视图中的角色: Spring安全插件提供ifAllGranted、ifAnyGranted、ifNoneGranted等标签来检查角色
例如,检查登录用户的管理员角色:
<sec:ifLoggedIn>
<sec:ifAllGranted roles="ROLE_ADMIN">
Admin resource
</sec:ifAllGranted>
</sec:ifLoggedIn>
(在 grails-2.2.2 和 springSecurityCorePlugin-1.2.7.3 中测试)
【讨论】:
<sec:ifAnyGranted roles="ROLE_ADMIN, ROLE_SUPER_ADMIN">
这个问题已经很老了,但我想我至少会发布一个似乎适用于 Grails 2.0 的答案。如果您使用的是 spring 安全插件,则包含一个名为 grails.plugins.springsecurity.SecurityTagLib 的标签库。
标签库有一个受保护的方法,hasAccess(),它可以采用与 g:link 标签相同的参数映射。因此,如果您扩展 SecurityTagLib,您可以调用 hasAccess() 并获得您想要的行为。为什么不将其外部化到可以注入的服务中,我无法理解,因为该功能似乎满足了明显的需求。
我们用它来包装g:link标签,只生成一个用户可以访问目标页面的链接:
def link = { attrs, body ->
if( hasAccess(attrs.clone(), "link") ) {
out << g.link(attrs, body)
}
else {
out << body()
}
}
【讨论】:
protected 甚至 private,因此您只需注入 SecurityTagLib 的实例并调用它。
controller 和 action(或 url)参数的映射并返回布尔值的方法,这就是 hasAccess() 所做的。
<sec:access> 会为您执行此操作。但这假设您在 GSP 和 Groovy 代码中。
SecurityTagLib securityTagLib = (SecurityTagLib)Holders.grailsApplication.mainContext.getBean('grails.plugins.springsecurity.SecurityTagLib')注入了!
【讨论】:
我不确定在 Groovy 中,但在 Java 中(所以我也认为是 Groovy...)你可以这样做(减去 NPE 检查):
GrantedAuthority[] authorities = SecurityContextHolder.getContext().getAuthentication().getAuthorities();
boolean isAdmin = false;
for(GrantedAuthority authority : authorities) {
String role = authority.getAuthority();
if(role != null && role.equals("ROLE_ADMIN")) {
isAdmin = true;
break;
}
}
至于是否支持该操作,您必须调用 RequestMap 服务来获取映射的角色,并查看它是否包含找到的用户角色。
【讨论】:
据我所知,似乎没有一种简单的方法可以做到这一点。
您可以通过执行以下操作注入 grails AuthenticatedVetoableDecisionManager 的实例,它是 spring 的 AbstractAccessDecisionManager 的一个具体类:
def accessDecisionManager
这有一个“决定”方法,它需要 3 个参数
decide(Authentication authentication, Object object, ConfigAttributeDefinition config)
这可能是您需要调用并传递正确内容的方法,以确定具有身份验证凭据的用户是否可以访问该“对象”(看起来通常是请求/响应)。一些额外的挖掘可能会证明这里可行。
短期而言,使用 ifAnyGranted taglib 可能更容易,正如另一张海报提到的那样。
【讨论】:
在处理视图和标签库中的权限时,您可以使用插件提供的AuthorizeTagLib。
例如,如果您不希望未经身份验证的用户在列表中显示菜单项,则可以使用:
<g:isLoggedIn>
<li>Restricted Link</li>
</g:isLoggedIn>
如果您定义了更具体的角色并且这些角色与您的控制器/操作请求映射相关联,您可以使用其他标签,例如:
<g:ifAllGranted role="ROLE_ADMINISTRATOR">
<li>Administrator Link</li>
</g:ifAllGranted>
根据我的经验,目前还没有一种将请求映射与您的标记相关联的好方法 - 我认为您将不得不使用上述一些标签来限制对特定 GSP 中内容的访问。
我认为 Burt Beckwith 未来对插件进行了修改(目前正在提供beta version),该插件集成了一些 ACL 东西,将来可能会更好地解决这个问题,但就目前而言,我认为最好的方法是一个混合请求映射 + GSP 标签一个。
【讨论】:
你必须配置文件config/SecurityConfig.groovy(如果它不存在,创建它,这会覆盖默认的安全配置)
添加此条目:
requestMapString = """\
CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
PATTERN_TYPE_APACHE_ANT
/=IS_AUTHENTICATED_REMEMBERED
/login/auth=IS_AUTHENTICATED_ANONYMOUSLY
/login/authajax=IS_AUTHENTICATED_ANONYMOUSLY
/login/authfail=IS_AUTHENTICATED_ANONYMOUSLY
/js/**=IS_AUTHENTICATED_ANONYMOUSLY
/css/**=IS_AUTHENTICATED_ANONYMOUSLY
/images/**=IS_AUTHENTICATED_ANONYMOUSLY
/plugins/**=IS_AUTHENTICATED_ANONYMOUSLY
/**=IS_AUTHENTICATED_REMEMBERED
"""
这意味着您必须登录才能进入该站点。但是所有资源(css、js、图像等)都无需身份验证即可访问。
如果您想要特定角色,只需输入特定控制器: 例如,对于 UserController:
/user/**=ROLE_ADMIN
/role/**=ROLE_ADMIN
欲了解更多信息:http://www.grails.org/AcegiSecurity+Plugin+-+Securing+URLs
问候
【讨论】: