49

I want to display some content conditionally based on Roles using Spring Security JSP taglibs. But in Spring Security 3.1.x is checking for only one role.

I can use but ifAllGranted is deprecated.

Any help?

K. Siva Prasad Reddy
  • 11,786
  • 12
  • 68
  • 95

5 Answers5

91

There is a special security expression in spring security:

hasAnyRole(list of roles) - true if the user has been granted any of the roles specified (given as a comma-separated list of strings).

I have never used it but I think it is exactly what you are looking for.

Example usage:

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

Here is a link to the reference documentation where the standard spring security expressions are described. Also, here is a discussion where I described how to create custom expression if you need it.

Community
  • 1
  • 1
dimas
  • 6,033
  • 36
  • 29
  • It worked :-) (User/Admin) But any way to check for hasAllRoles(role1, role2)? – K. Siva Prasad Reddy Jul 13 '12 at 11:40
  • About your last question: "But any way to check for hasAllRoles(role1, role2)?" - I don't think that it is possible. But you can crete your custom expression (I gave a link), and in code check whatever you want. – dimas Jul 13 '12 at 11:51
  • 4
    On your second question you should be able to use 'hasRole' with the 'and' operator like hasRole('ADMIN') and hasRole('DEVELOPER') to achieve this functionality. – bh5k Apr 01 '13 at 21:20
  • If you want to have content for people who have role1 AND role2, I suppose you could just nest two blocks. – Michael Dec 17 '14 at 09:32
  • `hasAnyRole` cannot logically replace `ifAllGranted`; please see my answer below – acidnbass Nov 18 '16 at 00:51
8

@dimas's answer is not logically consistent with your question; ifAllGranted cannot be directly replaced with hasAnyRole.

From the Spring Security 3—>4 migration guide:

Old:

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

New (SPeL):

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

Replacing ifAllGranted directly with hasAnyRole will cause spring to evaluate the statement using an OR instead of an AND. That is, hasAnyRole will return true if the authenticated principal contains at least one of the specified roles, whereas Spring's (now deprecated as of Spring Security 4) ifAllGranted method only returned true if the authenticated principal contained all of the specified roles.

TL;DR: To replicate the behavior of ifAllGranted using Spring Security Taglib's new authentication Expression Language, the hasRole('ROLE_1') and hasRole('ROLE_2') pattern needs to be used.

acidnbass
  • 315
  • 3
  • 12
  • Thank you very much. Also it works for privileges similarly.
    This text is only visible to an user who has the 'CREATE_GROUP' and 'CHANGE_PASSWORD_PRIVILEGE' privileges together.
    – ÖMER TAŞCI Sep 14 '17 at 08:15
1

i used hasAnyRole('ROLE_ADMIN','ROLE_USER') but i was getting bean creation below error

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/*]

then i tried

access="hasRole('ROLE_ADMIN') or hasRole('ROLE_USER')" and it's working fine for me.

as one of my user is admin as well as user.

for this you need to add use-expressions="true" auto-config="true" followed by http tag

<http use-expressions="true" auto-config="true" >.....</http>
Musaddique
  • 443
  • 5
  • 9
1

you can try in this way if you are using thymeleaf

sec:authorize="hasAnyRole('ROLE_ADMIN','ROLE_USER')"

hasAnyRole will return true if the authenticated principal contains at least one of the specified roles,false otherwise.

Please note you have to use sec tag in your html declaration tag like this

<html xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4">
TanvirChowdhury
  • 2,498
  • 23
  • 28
1

Within Spring Boot 2.4 it is

sec:authorize="hasAnyRole('ROLE_ADMIN')

Ensure that you have

thymeleaf-extras-springsecurity5

in your dependencies. Also make sure that you include the namespace

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

in your html...

  • What does including thymleaf in the namespace do . I always take that out and haven't had problems yet. – Mustafa Apr 24 '22 at 12:01