DuyHai's Java Blog

Spring Security part V : Security tags

Advertisements

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:

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:

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:

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

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:

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:

The tag exposes the following attributes:

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