Looping in OGNL
A question that comes up often is, "How to do I construct a loop in OGNL?" For example, I might have a collection/array of objects that I need to loop through in order to check or modify the values in it. A very common use case is with group membership (I dealt with this topic in a Technical Roundtable: Managing Groups and OGNL).
As part of sending identity information, you often need to send the groups the user is a member of in an LDAP directory.
The memberOf attribute often contains a DN or distinguishedName in the following format:
CN=Managers,CN=Users,DC=company,DC=com
But let's say that your partner cannot handle the DN format and just wants the group name, which in our example is Managers. How do we remove all the extra bits of the DN to get it down to just the name? There are many ways to accomplish that task, but we will not digress too much. The Java SDK provides a class (javax.naming.ldap.LdapName) that will do the hard work for us, so we will simply use that.
See the complete list of articles in my OGNL series at the end of this article.
The second problem, and what interests us, is that usually you get multiple groups in the memberOf attribute; therefore, you need to loop through each one.
In my previous article, I first talked about curly {} braces and how they can be used to create a collection or array. In addition to creating a collection, the curly braces can also be used to let us step through a collection and even create a new one in the process.
I also talked about the how the org.sourceid.saml20.adapter.attribute.AttributeValue class is used to retrieve attributes available to us in the PingFederate context, either from an Adapter, assertion, or a data source (such as LDAP). If the attribute that PingFederate provides is multi-valued (i.e., a collection) we can use the getValues method to get this collection.
Taking those two bits of knowledge above and some Java know-how, we can create some code that looks like the following:
1. #groupCnOnly = new java.util.ArrayList(),
2. #groups = #this.get("ds.LDAP.memberOf")!=null?#this.get("ds.LDAP.memberOf").getValues() : {},
3. #i= 0,
4. #groups.{
5. #group = new javax.naming.ldap.LdapName(#groups[#i]),
6. #cn = #group.getRdn(#group.size() - 1).getValue().toString(),
7. #groupCnOnly.add(#cn),
8. #i = #i + 1
9. },
10. #this.get("ds.LDAP.memberOf")!=null? new org.sourceid.saml20.adapter.attribute.AttributeValue(#groupCnOnly) : null
I'm taking a slightly different approach of showing you all the code upfront, but now I'll explain it line-by-line (line numbers above should be removed when you copy this code into your own PingFederate environment):
First, let's see what we get from the data source in the memberOf attribute:
The results are:
Now the code:
The results of the code execution:
This code provides one solution to the looping problem. In my next OGNL installment, we'll discuss an alternative approach.
Stay tuned for more about OGNL. In the meantime please leave a comment on this post and let me know what topics you would like to see. Follow me on Twitter: @jdasilvaPI
****************************************
OGNL Blog Series:
John DaSilva develops training and solutions at Ping Identity.