如何使用 <sec:authorize access="hasRole('ROLES)"> 来检查多个角色?

Posted

技术标签:

【中文标题】如何使用 <sec:authorize access="hasRole(\'ROLES)"> 来检查多个角色?【英文标题】:How to use <sec:authorize access="hasRole('ROLES)"> for checking multiple Roles?如何使用 <sec:authorize access="hasRole('ROLES)"> 来检查多个角色? 【发布时间】:2012-07-13 05:29:44 【问题描述】:

我想使用 Spring Security JSP 标签库根据角色有条件地显示一些内容。 但是在 Spring Security 3.1.x 中只检查一个角色。

我可以使用,但 ifAllGranted 已弃用。

有什么帮助吗?

【问题讨论】:

【参考方案1】:

spring security中有一个特殊的安全表达式:

hasAnyRole(角色列表) - 如果用户被授予任何 指定的角色(以逗号分隔的字符串列表形式给出)。

我从未使用过它,但我认为它正是您想要的。

示例用法:

<security:authorize access="hasAnyRole('ADMIN', 'DEVELOPER')">
    ...
</security:authorize>

这是一个link to the reference documentation,其中描述了标准的弹簧安全表达式。另外,这里是discussion,我在其中描述了如何根据需要创建自定义表达式。

【讨论】:

它工作了 :-) (用户/管理员) 但是任何检查 hasAllRoles 的方法(角色1,角色2)? 关于您的最后一个问题:“但是有什么方法可以检查 hasAllRoles(role1, role2)?” - 我不认为这是可能的。但是您可以创建您的自定义表达式(我提供了一个链接),并在代码中检查您想要的任何内容。 关于第二个问题,您应该能够将 'hasRole' 与 hasRole('ADMIN') 和 hasRole('DEVELOPER') 等 'and' 运算符一起使用来实现此功能。 如果你想为拥有角色 1 和角色 2 的人提供内容,我想你可以嵌套两个块。 hasAnyRole 不能在逻辑上替换ifAllGranted;请看下面我的回答【参考方案2】:

@dimas 的回答在逻辑上与您的问题不一致; ifAllGranted不能直接替换为hasAnyRole

来自Spring Security 3—>4 migration guide:

旧:

<sec:authorize ifAllGranted="ROLE_ADMIN,ROLE_USER">
    <p>Must have ROLE_ADMIN and ROLE_USER</p>
</sec:authorize>

新(SPeL):

<sec:authorize access="hasRole('ROLE_ADMIN') and hasRole('ROLE_USER')">
    <p>Must have ROLE_ADMIN and ROLE_USER</p>
</sec:authorize>

直接用hasAnyRole替换ifAllGranted会导致spring使用OR而不是AND来评估语句。也就是说,如果经过身份验证的主体包含至少一个指定角色,hasAnyRole 将返回 true,而 Spring(现在从 Spring Security 4 开始不推荐使用)ifAllGranted 方法仅返回 @987654333 @ 如果经过身份验证的主体包含指定角色的所有

TL;DR:要使用 Spring Security Taglib 的新身份验证表达式语言复制 ifAllGranted 的行为,需要使用 hasRole('ROLE_1') and hasRole('ROLE_2') 模式。

【讨论】:

非常感谢。它也同样适用于特权。 此文本仅对同时拥有“CREATE_GROUP”和“CHANGE_PASSWORD_PRIVILEGE”权限的用户可见。【参考方案3】:

如果你正在使用百里香,你可以尝试这种方式

sec:authorize="hasAnyRole(T(com.orsbv.hcs.model.SystemRole).ADMIN.getName(),
               T(com.orsbv.hcs.model.SystemRole).SUPER_USER.getName(),'ROLE_MANAGEMENT')"

如果用户具有上述角色,则返回 true,否则返回 false。

请注意,您必须像这样在 html 声明标签中使用 sec 标签

<html xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4">

【讨论】:

【参考方案4】:

我使用了hasAnyRole('ROLE_ADMIN','ROLE_USER'),但我的 bean 创建低于错误

Error creating bean with name     'org.springframework.security.web.access.intercept.FilterSecurityInterceptor#0': Cannot create inner bean '(inner bean)' of type [org.springframework.security.web.access.expression.ExpressionBasedFilterInvocationSecurityMetadataSource] while setting bean property 'securityMetadataSource'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name '(inner bean)#2': Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [org.springframework.security.web.access.expression.ExpressionBasedFilterInvocationSecurityMetadataSource]: Constructor threw exception; nested exception is java.lang.IllegalArgumentException: Expected a single expression attribute for [/user/*]

然后我尝试了

access="hasRole('ROLE_ADMIN') or hasRole('ROLE_USER')" 对我来说工作正常。

因为我的用户之一是管理员和用户。

为此,您需要添加use-expressions="true" auto-config="true",后跟http标签

<http use-expressions="true" auto-config="true" >.....</http>

【讨论】:

【参考方案5】:

在 Spring Boot 2.4 中是

sec:authorize="hasAnyRole('ROLE_ADMIN')

确保你有

thymeleaf-extras-springsecurity5

在您的依赖项中。还要确保包含命名空间

xmlns:sec="http://www.thymeleaf.org/extras/spring-security"

在你的 html...

【讨论】:

以上是关于如何使用 <sec:authorize access="hasRole('ROLES)"> 来检查多个角色?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 sec:authorize with thymeleaf 向特定用户授权 html 元素?

在 jsp 页面中使用标签 <sec:authorize> 在 eclipse 中显示错误

使用 sec:authorize 加载 javascript

<sec:authorize> 不起作用

将 Spring Boot 1.5 升级到 2 <sec:authorize> 不起作用

<sec:authorize ifAnyGranted 或 ifAnyGranted 在 SPRING SECURITY 中不起作用