Spring Security part V : Security tags

Today we discuss about the security tags provided with Spring Security package. These tags allow you to customize your web pages to include/exclude elements based on user roles and credentials

The below description of Spring Security Tag is based on official Spring Security 3.1.0 RELEASE. It may not apply to older versions

I Configuration

To enable JSP page-level security, we need to import the Spring Security tag library as follow:

<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %>

We also need to add the spring security taglib Maven dependency into our project pom.xml

  	<dependency>
  		<groupId>org.springframework.security</groupId>
  		<artifactId>spring-security-taglibs</artifactId>
  		<version>3.1.0.RELEASE</version>
  		<type>jar</type>
  		<scope>compile</scope>
  	</dependency>

II Security tags

 

A The Authorization tag

To enable the rendering of some portion based on user credentials, we can rely on the <sec:authorize> tag:

<sec:authorize access="hasRole('admin')">
	<table>
  		<tr>
  	  	  	<td>xxx</td>
  	  	  	<!-- Some administrator data here -->
  	  	</tr>
  	</table>
</sec:authorize>

<sec:authorize access="hasRole('guest')">
	Restricted data, you are not allowed to access this resource  	
</sec:authorize>

The “access” attribute allows us to define the access rules. In the above example we simply check for user role (admin or guest). The hasRole is a SpEL (Spring Expression Language) syntax. Complete list of spEL expressions for security is given below:

  • hasRole([role]): Returns true if the current principal has the specified role.
  • hasAnyRole([role1,role2]): Returns true if the current principal has any of the supplied roles (given as a comma-separated list of strings)
  • principal: Allows direct access to the principal object representing the current user
  • authentication: Allows direct access to the current Authentication object obtained from the SecurityContext
  • permitAll: Always evaluates to true
  • denyAll: Always evaluates to false
  • isAnonymous(): Returns true if the current principal is an anonymous user
  • isRememberMe(): Returns true if the current principal is a remember-me user
  • isAuthenticated(): Returns true if the user is not anonymous
  • isFullyAuthenticated(): Returns true if the user is not an anonymous or a remember-me user

Among this list, only some expressions are usefull for the access attribute, mainly hasRole([role]), hasAnyRole([role1,role2]), isAnonymous(), isRememberMe(), isAuthenticated() and isFullyAuthenticated(). The other expressions are more informative and serve in different contexts (we’ll see them soon)

Apart from the “access” attribute, the <sec:authorize> tag offers other interesting attributes:

  • url: an URL within the application. The tag <sec:authorize> is renderd if the user is grated access to this URL (based on rules defined by the FilterSecurityInterceptor)
  • method: GET or POST. Specify the HTTP method user to access the url. This attribute can only be used along with the previous url attribute.
  • var: a page scope variable to store the evaluation of this tag (true or false) so it can be re-used later in the page for different purpose.

Please note that for the “url” attribute to work, you need to declare an additional DefaultWebInvocationPrivilegeEvaluator bean in the Spring context with the filterSecurityInterceptor injected as constructor argument:

<!-- Filter for role checking -->
<bean id="filterSecurityInterceptor" class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
	<property name="authenticationManager" ref="authenticationManager"/>
	<property name="accessDecisionManager" ref="httpRequestAccessDecisionManager"/>
	<property name="securityMetadataSource">
		<sec:filter-security-metadata-source lowercase-comparisons="true" request-matcher="ant" use-expressions="true">
			<sec:intercept-url pattern="/pages/Security/**" access="permitAll"/>
			<sec:intercept-url pattern="/resources/**" access="permitAll"/>
			<sec:intercept-url pattern="/pages/Settings/**" access="hasRole('SETTINGS')"/>
			<sec:intercept-url pattern="/pages/Home/*" access="hasRole('HOME')"/>              
			<sec:intercept-url pattern="/pages/Admin/**" access="hasRole('ADMINISTRATOR')"/>
			<sec:intercept-url pattern="/servlet/Download" access="hasAnyRole('DOWNLOAD','PREMIUM_ACCOUNT')"/>
                
			<sec:intercept-url pattern="/**" access="isAuthenticated()"/>
		</sec:filter-security-metadata-source>
	</property>
</bean>

<!-- webInvocationPrivilegeEvaluator necessary to use <sec:authorized url="xx"> -->
<bean id="webInvocationPrivilegeEvaluator" class="org.springframework.security.web.access.DefaultWebInvocationPrivilegeEvaluator">
	<constructor-arg ref="filterSecurityInterceptor">
</bean>

Below is an example of the var attribute usage:

<sec:authorize access="hasRole('admin')" var="isAdmin">
	<table>
  		<tr>
  	  	  	<td>xxx</td>
  	  	  	<!-- Some administrator data here -->
  	  	</tr>
  	</table>
</sec:authorize>
...
<c:if test="${isAdmin}">
  // Some block here if the user is Admin
</c:if>

 

B The Authentication tag

The &ltsec:authentication> tag gives access to the Authentication object of the security context. The attribute “property” allows us to access some property of the Authentication object itself and display it directly to the page.

The Authentication interface exposes the following methods:

  • authorities: collection of GrantedAuthority instances. Corresponds in most case to user roles
  • credentials: user’ credentials (usually password)
  • details: object containing the details of the authentication process itself. The content of this object depends on the implementation of the Authentication interface. The default implementation returns null
  • principal: the principal object, which is most of the time an instance of the UserDetails interface
  • isAuthenticated: return true or false whether the use is authenticated or not

As with the previous tag, the &ltsec:authentication> tag offers some interesting other attributes:

  • var: a page variable to store the result of the property attribute so it can be re-used later in the page for different purposes
  • scope: scope of the above “var” attribute. Can be “page“, “request“,”session” or “application
  • htmlEscape: if true, enable HTML escape for the “property” attribute display

Usage examples:

<!-- Credentials display -->
Your password is <sec:authentication property="credentials"/>
...

<!-- Roles display -->
<sec:authentication property="authorities" var="roles" scope="page" />
Your roles are:
<ul>
	<c:forEach var="role" items="${roles}">
 	<li>${role}</li>
	</c:forEach>
</ul>

<!-- Username display -->
Your username is <sec:authentication property="principal.username"/>

 

C The Accesscontrollist tag

This <sec:accesscontrollist> tag is rarely used and can only be evaluated if Spring Security’s ACL module is activated.

The available attributes are:

  • hasPermission: a list of permission (coma as separator) to be checked against domain object. The permission strings will be converted first into Permission instance by the PermissionFactory before performing evaluation. The evaluation is true if at least one of the listed permission is found in the domain object
  • domainObject: domain object for which the above permissions are evaluated
  • var: a page scope variable to store the evaluation of this tag (true or false) so it can be re-used later in the page for different purpose

Usage example:


<sec:accesscontrollist hasPermission="admin,designer" domainObject="${someObject}">
	//Displayed only if the domainObject has "admin" OR "designer" permission  
</sec:accesscontrollist> 

III Security tags for Facelet

The above security tags are only available for JSP pages. If you are a JSF-user with Facelet as templating solution, no chance.

Luckily, some brillant people had a good idea to adapt these tags for Facelet. You can download the binaries here http://www.dominikdorn.com/facelets/

By looking around, I found out that there is a tag library out there for JSF shipped with Spring Web Flow: http://static.springsource.org/spring-webflow/docs/2.2.x/reference/html/ch13s09.html

You need to add the following dependency to your pom.xml

<dependency>
	<groupId>org.springframework.webflow</groupId>
	<artifactId>spring-faces</artifactId>
	<version>2.2.0.RELEASE</version>
</dependency>

This jar contains many packages, among others the org.springframework.faces.security which is of interest. Alternatively if you do not want to get all the packages not related to security you can just copy the org.springframework.faces.security package into your source code.

Adding the above dependency is not enough. You need also to declare this new taglib in a springsecurity.taglib.xml file for example:

<?xml version="1.0"?>
<!DOCTYPE facelet-taglib PUBLIC
  "-//Sun Microsystems, Inc.//DTD Facelet Taglib 1.0//EN"
  "http://java.sun.com/dtd/facelet-taglib_1_0.dtd">
<facelet-taglib>
	<namespace>http://www.springframework.org/security/tags</namespace>
	<tag>
		<tag-name>authorize</tag-name>
		<handler-class>org.springframework.faces.security.FaceletsAuthorizeTagHandler</handler-class>
	</tag>
	<function>
		<function-name>areAllGranted</function-name>
		<function-class>org.springframework.faces.security.FaceletsAuthorizeTagUtils</function-class>
		<function-signature>boolean areAllGranted(java.lang.String)</function-signature>
	</function>
	<function>
		<function-name>areAnyGranted</function-name>
		<function-class>org.springframework.faces.security.FaceletsAuthorizeTagUtils</function-class>
		<function-signature>boolean areAnyGranted(java.lang.String)</function-signature>
	</function>
	<function>
		<function-name>areNotGranted</function-name>
		<function-class>org.springframework.faces.security.FaceletsAuthorizeTagUtils</function-class>
		<function-signature>boolean areNotGranted(java.lang.String)</function-signature>
	</function>
	<function>
		<function-name>isAllowed</function-name>
		<function-class>org.springframework.faces.security.FaceletsAuthorizeTagUtils</function-class>
		<function-signature>boolean isAllowed(java.lang.String, java.lang.String)</function-signature>
	</function>
	<function>
		<function-name>access</function-name>
		<function-class>org.springframework.faces.security.FaceletsAuthorizeTagUtils</function-class>
		<function-signature>boolean access(java.lang.String)</function-signature>
	</function>	
</facelet-taglib>

The above declaration sheds some light on the available infrastructure:

  • authorize: new tag
  • areAllGranted(roles): new EL function. Returns true if all listed roles are granted to the current user
  • areAnyGranted(roles): new EL function. Returns true if at least one listed role is granted to the current user
  • areNotGranted(roles): new EL function. Returns true if all listed roles are not granted to the current user
  • isAllowed(url,method): new EL function. Returns true if the given url with corresponding HTTP method can be accessed by the current user
  • access(webExpression): new EL function. Returns true if the given web expression holds for the current user

The tag exposes the following attributes:

  • access: see above
  • url: see above
  • method: see above
  • areAllGranted: see above
  • areAnyGranted: see above
  • areNotGranted: see above
  • var: set the result of the access evaluation (true or false) into the Faces context

We need to declare this taglib in the web.xml file:

<context-param>
	<param-name>javax.faces.FACELETS_LIBRARIES</param-name>
	<param-value>/WEB-INF/springsecurity.taglib.xml</param-value>
</context-param>

Usage example:

<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:ui="http://java.sun.com/jsf/facelets" 
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:sec="http://www.springframework.org/security/tags">
<ui:composition template="/pages/Templates/techWebTemplate.xhtml">
	...
	...
	<h:panelGroup  id="secureBlock" layout="block"
		rendered="#{sec:areAnyGranted('DESIGNER, ADMINISTRATOR')}">
		// Section rendered only for DESIGNER or ADMINISTRATOR roles
	</h:panelGroup>						
	...
	...
	<sec:authorize access="hasAnyRole('ADMINISTRATOR',"DESIGNER')">
		<h:panelGroup id="administrationBlock" layout="block">
		...
		</h:panelGroup>
	</sec:authorize>    
</ui:composition>
</html>

Please pay attention to the special typo for the tag version and the EL function version.

<sec:areAnyGranted(‘DESIGNER, ADMINISTRATOR’)>: the roles are separated by a coma and the whole chain is enclosed in simple quotes

hasAnyRole(‘ADMINISTRATOR’,’DESIGNER’): the roles are enclosed first in simple quotes then separated by a coma

Advertisements

About DuyHai DOAN
Cassandra Technical Evangelist. LinkedIn profile : http://fr.linkedin.com/pub/duyhai-doan/2/224/848. Follow me on Twitter: @doanduyhai for latest updates on Cassandra

23 Responses to Spring Security part V : Security tags

  1. Pingback: Spring MVC part VI: ThymeLeaf advanced usage « Yet Another Java Blog

  2. Pingback: Spring MVC part IV: ThymeLeaf advanced usage « Yet Another Java Blog

  3. Rafael says:

    Great blog entry. Thank you very much for this information¬°

    • Rafael says:

      I edit for to say that in version 5.0:

      – It isnt necesary to create file springsecurity.taglib.xml
      – Maven dependencies are not correct in the principal website. The correct dependencies are:

      org.springframework.security
      facelets-taglib-jsf20-spring-3
      0.5

      – The name of methods have changed: areAllGranted is ifAllGranted,….. It is advisable to see javadoc for version 5.0.

      Kind regards.

      • DuyHai DOAN says:

        Thanks Rafael. By looking into the code again, I realized that what is in the article is not the code from http://www.dominikdorn.com/facelets/ but an extract of the spring-faces.jar from Spring Webflow. I just modify the article accordingly.

        Thank you

      • ouafae says:

        Hi , I use the same dependencies in my project ( facelets-taglib-jsf20-spring-3
        0.5 and spring-security) but I have problem when I use for example :

        i get an ERROR : Function ‘:ifAnyGranted’ not found, and if i use :
        my compenent

        it’s ingnored , my compenent is not hiding.

  4. DuyHai DOAN says:

    @ouafae

    I have updated the article, you should use “areAnyGranted” instead of “ifAnyGranted”

  5. I’m not able to make it work… JSF 1.2 & spring 3.1, security 3.1 & webflow 2.3 library…
    Every sec tags are ignored or not found. I use the right springsecurity.taglib.xml for JSF 1.2 as stated in spring webflow configuration

    • DuyHai DOAN says:

      @Andrea

      Did you declare the taglib file in the web.xml as mentioned above ?

      javax.faces.FACELETS_LIBRARIES
      /WEB-INF/springsecurity.taglib.xml

      Can you put your code on GitHub or a public repo so I can have a look ?

  6. Hong says:

    I can not make it work.

    I use JSF 2.1.7 and spring webflow, It seems that the stop working whenever I introduce the spring webflow, below is my maven dependency:

    org.springframework.webflow
    spring-faces
    2.3.1.RELEASE

    commons-logging
    commons-logging

  7. Richie says:

    Hello Hong
    Do you implement the Authentication tag in a similar way to the Authorization tag for jsf2 with facelets. Is there a FaceletsAuthenticationTagUtils that I have to setup in springsecurity.taglib.xml. I’m trying to display the principal.username

    • vijay says:

      Hi Richie,
      Any luck even i try to display principal.username in jsf, but no luck.

  8. y says:

    great tip. thanks!

  9. Leaon says:

    Why the tag in my page output nothing?

  10. Ilse says:

    Howdy! I could have sworn Ive been to this website before but after browsing through some of the post I realized its new to me.

    Anyhow, Im definitely happy I found it and Ill be
    book-marking and checking back frequently!

  11. JP Villemin says:

    Nice tip. I’m actually facing a problem with JSF2 and Taglib security…I post on StackOverflow http://stackoverflow.com/questions/19387228/spring-security-taglib-authorize-authentication-are-not-working-with-role-hierar
    If you have some time to loose … : ) Thanks

  12. Pingback: Spring Security 3.1.4 taglib authorize/authentication are not working with role hierarchy in JSF 2.1 | Technology & Programming Answers

  13. mansoor67890 says:

    Hi, Is there any way I can store username in javascript variable?

  14. wyanglau says:

    Reblogged this on ryanuoft and commented:
    Repost of this article discussing about spring tag

Leave a Reply to wyanglau Cancel reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: