I was working on a Spring framework based application where in I wanted to incorporate Spring Security quickly. While doing so, there was a need for me to display links in the UI based on the logged in user roles. The UI that I was using was Apache Velocity. I knew the fact that there were JSPTagLibs available for Spring Security.
I had incorporated the basic security and I was using Spring Security 3.0.4. So, I was exploring on using the Spring Security JSP tab library into the Apache Velocity Templates for displaying a few links based on the roles of the principal who had logged in! In this juncture, I wanted to use the JSPTagLibs of Spring security in the velocity template.
When I explored options on this, it was so unfortunate that I could not find any. But , when I confronted the resolved
JIRA issue on 'Support for jsp taglibs in freemarker templates', initially I presumed that the same or a similar structure might be present for velocity too.
But the freemarker blog article on '
Velocity or FreeMarker: Looking at 5 Years of Practical Experience' made me realize that my presumption was wrong.
Further to this, I had to explore alternative options.
The best and the quickest alternative was to make use of a wrapper class that can get me the objects that I needed in the velocity views. For this, I needed a wrapper class for the Security tag library that can get me the objects/properties that I needed to make use of in my views. So I went ahead and made use of the following wrapper class. I had a wrapper class as shown below. This contained the properties/methods related to the security that I intended to make use of inside my velocity views.
package com.utils;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
public class VelocitySecUser {
/**
* Gets the user name of the user from the Authentication object
*
* @return the user name as string
*/
public static String getPrincipal() {
Object obj = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
if (obj instanceof UserDetails) {
return ((UserDetails) obj).getUsername();
} else {
return "Guest";
}
}
/**
* Is the user granted all of the grantedAuthorities passed in
*
* @param roles a string array of grantedAuth
* @return true if user has all of the listed authorities/roles, otherwise false
*/
public static boolean allGranted(String[] checkForAuths) {
Set<String> userAuths = getUserAuthorities();
for (String auth : checkForAuths) {
if (userAuths.contains(auth))
continue;
return false;
}
return true;
}
/**
* Is the user granted any of the grantedAuthorities passed into
*
* @param roles a string array of grantedAuth
* @return true if user has any of the listed authorities/roles, otherwise false
*/
public static boolean anyGranted(String[] checkForAuths) {
Set<String> userAuths = getUserAuthorities();
for (String auth : checkForAuths) {
if (userAuths.contains(auth))
return true;
}
return false;
}
/**
* is the user granted none of the supplied roles
*
* @param roles a string array of roles
* @return true only if none of listed roles are granted
*/
public static boolean noneGranted(String[] checkForAuths) {
Set<String> userAuths = getUserAuthorities();
for (String auth : checkForAuths) {
if (userAuths.contains(auth))
return false;
}
return true;
}
private static Set<String> getUserAuthorities() {
Object obj = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
Set<String> roles = new HashSet<String>();
if (obj instanceof UserDetails) {
Collection<GrantedAuthority> gas = ((UserDetails) obj).getAuthorities();
for (GrantedAuthority ga : gas) {
roles.add(ga.getAuthority());
}
}
return roles;
}
}
Further to this, you might have to add this as a bean into the attribute map of your velocity view resolver as given below:
<br /> <bean id="viewResolver" class="org.springframework.web.servlet.view.velocity.VelocityViewResolver"><br /> <property name=....//><br /> <property name="attributesMap"><br /> <map><br /> <entry key="sec"><ref bean="veloSecUserDetails"/></entry><br /> </map><br /> </property> <br /> </bean><br /> <bean id ="veloSecUserDetails" class ="com.utils.VelocitySecUser"/><br />
When this is done, automatically, you would have the object $sec accessible from within your velocity templates. You can start making use of this object in the velocity templates using the code shown below:
<br />Testing the Object $sec <br />Name of the principal is: ${sec.principal} <br />#if($sec.AllGranted("ROLE_USER")) <br /> The principal has USER role within the application<br />#end<br />
That is it!!Your code starts woking great and you have access to all the methods that you have it in the wrapper within your Apache velocity template on the flu!
I sincerely express my thanks to the discussion at
Spring forum since the base ideas are basically discussed here as the solution for accessing spring security tags within Velocity Templates!
As usual, I look forward getting your hollers/feedback regarding this post any time!