I am creating a sample application with the springframework. I use Acegi or Spring security as the security framework. On this blog I have multiple items that relate to acegi. I think more will come. This one is about a tag library I created. I wanted to be able to print more details from the UserDetails object that resides in the SecureContext. There are multiple ways to realize this. The most obvious is using a scriptled.

<%=((PersonDetails)((SecureContext)net.sf.acegisecurity.context.ContextHolder.getContext())
    .getAuthentication().getPrincipal()).getFirstName()%>

But if you want to show multiple properties this is not very nice and I like to minimize the amount of scriptlets in jsp code. Therefore I wanted to use a tag library. You can ofcourse use the standard tag library from acegi

<authz:authentication operation=”principal”/>

This can only show the username. But the concept is good, and ready for extending. Therefore I created an extended version of the tag library. I introduced a second property called “prefix” and now you can call any “get*” method or “is*” method. If you want to call other methods as well, it is very easy to change the current implementation.

Time to have a look at some parts of the code, I present the doStartTag method:

1. public int doStartTag() throws JspException {
2.   if ((null == operation) || “”.equals(operation)) {
3.     return Tag.SKIP_BODY;
4.   }
5.
6.   validateArguments();
7.
8.   if ((ContextHolder.getContext() == null)
9.       || !(ContextHolder.getContext() instanceof SecureContext)
10.      || (((SecureContext) ContextHolder.getContext()).getAuthentication() == null)) {
11.    return Tag.SKIP_BODY;
12.  }
13.
14.  Authentication auth = ((SecureContext) ContextHolder.getContext()).getAuthentication();
15.
16.  if (auth.getPrincipal() == null) {
17.    return Tag.SKIP_BODY;
18.  } else if (auth.getPrincipal() instanceof UserDetails) {
19.    writeMessage(invokeOperation(auth.getPrincipal()));
20.
21.    return Tag.SKIP_BODY;
22.  } else {
23.    writeMessage(auth.getPrincipal().toString());
24.
25.    return Tag.SKIP_BODY;
26.  }
27.}

Lines 1-12 are validation code, just trying your tag not to throw an unexpected exception. Line 14 obtains the Authentication object from the SecureContext. This object contains the principal which we are after. If the Principal is of type UserDetails (the interface your custom implementation should implement), we call the invokeOperation method.

1. private String invokeOperation(Object obj) throws JspException {
2.   Class clazz = obj.getClass();
3.   String methodToInvoke = getOperation();
4.   StringBuffer methodName = new StringBuffer();
5.   methodName.append(getMethodPrefix());
6.   methodName.append(methodToInvoke.substring(0,1).toUpperCase());
7.   methodName.append(methodToInvoke.substring(1));
8. 
9.   Method method = null;
10.  try {
11.    method = clazz.getDeclaredMethod(methodName.toString(),null);
12.  } catch (SecurityException se) {
13.    throw new JspException(se);
14.  } catch (NoSuchMethodException nsme) {
15.    throw new JspException(nsme);
16.  }
17.  Object retVal =null;
18.
19.  try {
20.    retVal = method.invoke(obj,null);
21.  } catch (IllegalArgumentException iae) {
22.    throw new JspException(iae);
23.  } catch (IllegalAccessException iae) {
24.    throw new JspException(iae);
25.  } catch (InvocationTargetException ite) {
26.    throw new JspException(ite);
27.  }
28.  if (retVal == null) {
29.    retVal = “”;
30.  }
31.  return retVal.toString();
32.}

lines 3-7 create the name of the method to call
lines 9 -16 create the Method instance to be invoked
lines 19-27 do the real invocation of the method.

As you can see it is faily easy to create the extende taglib by using reflection to call the right methods on the UserDetails implementation. I have used this file and the tld file in my sample that can be found on javaforge. You can also have a look at the files from this website, but then there is no working sample.

AuthenticationTag.java
CustomAuthenticationTag.tld

References
Acegi security

Acegi authentication tag library