You are here

JSP IPerson Luminis IV - How to query

Submitted by Jason on Thu, 09/13/2007 - 18:08

In Luminis III, we created a single JSP page that would pass combinations of user LDAP information to external systems in order to provide single sign-on and more (http://www.lumdev.net/node/220). This was accomplished using the API's that the uPortal provides. Namely the PersonDirectory and IPerson architectures.

Some of the external systems were not traditional web sites with login pages. If I had been more familiar with GCF, I might have been able to accomplish the same thing, however, I preferred to build in a more well known language.

The downside to this approach:
1. uPortal may not be the core of the Sungard Portal forever
2. Sungard only supports the web proxy channel as a means to query the ldap within a use session, so for JSP , you are on your own.

The upside to this approach:
1. Connections to external systems are designed in a non-proprietary language, which should be easy for other developers to work with.
2. Should the time come when uPortal is not the base of Luminis, we will likely need to only redesign the user attribute query section of the JSP page, because of the prevalence of java in the web world.
3. JSP allows us to do more complicated sso operations, such as creating hashes and timestamps that conform to specific external systems requirements.

------------------------------------------------------------------------------------------------------------

The major difference between Luminis III and Luminis IV is the the deprecation of the personDirs.xml file. More information can be found here: http://www.ja-sig.org/wiki/display/UPC/PersonDirectory

The first thing I wanted to learn, was whether there were any backward compatible methods that would allow us to keep using personDirs.xml and our old JSP code. There is, and information about it is located here: http://www.ja-sig.org/wiki/display/UPC/LegacyPersonAttributeDao

The first thing I noticed about the legacy class, was that it referenced personDirs.xml in a the directory /properties. Another thing I noticed, was when I attempted to use the legacy method by replacing the class of the bean id personAttributeDao, that the tomcat server would not boot.

I ended up giving up on using the legacy method, so if anyone discovers how to make it work, I'm sure it would be of great interest for folks using personDirs.xml extensively.

----------------------------------------------------

The result of this reading is the following:

1. The file to modify to allow ldap or jdbc queries is now located at $CP_WEBINF/uPortal/properties/personDirectory.xml
2. The documentation at http://www.ja-sig.org/wiki/display/UPC/PersonDirectory is incomplete and in one place, inaccurate, at least as implemented in the Luminis system.
3. Our original JSP code still works to query user information within their session.

-------------------------------------------------------

The solution:

In your personDirectory.xml file, scroll down or search for <property name="ldapAttributesToPortalAttributes">

You will see a section enclosed in a <map> tag. Contained in that map tag are many <entry key="...> lines, with <value>urn....</value> MACE values.

For each item you want to query in your jsp, you need to add a set tag, and a value tag. The set tag just encloses the values, and the value tag contains the ldap attribute name. The entry key is what you will use to refer to the ldap attribute in your jsp page.

So if I want to query someone's user name in my jsp, my personDirectory needs to have an entry key that looks like this:

<entry key="pdsLoginId"> (or whatever you want to call it, username, olduid, whatever).
<set> (not sure why the set tag is missing on http://www.ja-sig.org/wiki/display/UPC/PersonDirectory)
<value>urn:sungardhe:dir:loginId</value> (I chose to leave sungards original value)
<value>pdsLoginId</value> (the exact name of the ldap attribute you want)
</set>
</entry>

Once that is done, you'll need to restart the webserver to get the xml file re-read.

The jsp page looks like this:

<%@ page language="java" contentType="text/html" %>
<%@ page import="java.util.*" %>
<%@ page import="org.jasig.portal.security.provider.*" %>
<%@ page import="org.jasig.portal.security.*" %>
<%@ page import="javax.servlet.http.HttpServletRequest" %>
<%@ page import="java.security.*" %>
<%@ page import="java.text.SimpleDateFormat" %>
<%@ page import="java.lang.*" %>


<%!
 private String getUserID(HttpServletRequest hsr)
	throws PortalSecurityException
 {
 	StringBuffer sb = new StringBuffer(); 
	SimplePersonManager spm = new SimplePersonManager();
	IPerson i = spm.getPerson(hsr);
	Object [] idAllArray = i.getAttributeValues("pdsExternalSystemID") ; 
	
	String goodStr = "";
	for (int loop=0; loop < idAllArray.length; loop++) 
	{
		String checkStr = idAllArray[loop].toString() ;
		String lowcheckStr = checkStr.toLowerCase() ; 
		if (lowcheckStr.indexOf("::sct") > 0) 
		{
			if ((lowcheckStr.indexOf("::sctinb") < 1 ) && (lowcheckStr.indexOf("::sctssb") < 1 ))
			{
				goodStr = lowcheckStr.toString();
			}
		}
	}
	int n = goodStr.indexOf("::sct") ; 
	String str = goodStr.substring(n-9, n) ; 
	sb.append(str.toUpperCase());
	return sb.toString();
}

private String getThirdPartyID(HttpServletRequest hsr)
	throws PortalSecurityException
 {
 	StringBuffer sb = new StringBuffer(); 
	SimplePersonManager spm = new SimplePersonManager();
	IPerson i = spm.getPerson(hsr);
	sb.append( (String)i.getAttribute("uid"));
	return sb.toString();
}

private String getFullName(HttpServletRequest hsr)
	throws PortalSecurityException
 {
 	StringBuffer sb = new StringBuffer(); 
	SimplePersonManager spm = new SimplePersonManager();
	IPerson i = spm.getPerson(hsr);
	sb.append( (String)i.getAttribute("cn"));
	return sb.toString();
}

etc..
%>

You'll note at the top that values like pdsExternalSystemID are going to return multiple values, so you need to put them in an array (or any means) so that you can return the one/ones you want.

There are other ways to return those values, you can see a lumdev comment, suggesting a different way here: http://www.lumdev.net/node/220

Once you have that part of the jsp done, you can then use the values. For our systems, it worked well to have several sections like this:

A link on our portal to our billing system might look like this:

http://my.pcc.edu/jsp/sso.jsp?app=ebill

<%
String urlstr = request.getParameter("app") ; (grab the app parameter from the URL)

if (urlstr.equals("ebill")) { (if the link app value is ebill, then do the ebill stuff in sso.jsp)
*Do a bunch of hashes and stuff that ebill needs*
somestringtopasstoEbill = getUserID(request)+whateveritneeds
}

getUserId(request) returns the pdsExternalSystemID that we queried way up at the top of the jsp.

Next we need to send this info off to the ebill site. There are of course many ways to do this, javascript, meta refresh, whatever.

<% if (urlstr.equals("ebill")) { %>
<META HTTP-EQUIV="Refresh" CONTENT="1;URL=https://quikpayasp.com/pcc/tuition/payer.do?giveme=<%= somestringtopasstoEbill %>" >
<% } %>

Luminis Version:

Attachments: 

Comments

I think if you reference the existing value names, you don't have to add the "set" tags. For example:

use
sb.append( (String)i.getAttribute("urn:sungardhe:dir:loginId"));
instead of
sb.append( (String)i.getAttribute("uid"));

--
David McMillan

Yes, I think thats right.

Most of our applications that the jsp feeds were expecting certain names though, so rather than mapping the urn:sungardhe:dir.... values to what each application wanted, I ended up 'discovering' the set tags.

I was slightly concerned that I would trip over lots of issues for this. (The most likely being that my jsp classpath would not include the org.jasig.* - as I am putting my jsp outside of some of the Luminis wrappers)

  • step 1) update $CP_WEBINF/uPortal/properties/personDirectory.xml
    ... simply add in a single line
    ... <entry key="pdsExternalSystemID"><value>urn:sgheX:dir:esId</value></entry>
  • note I made up my own eXtension to the sghe urn namespace - this is not registered either
  • step 2) copy pretty much the jsp from this thread
  • step 3) call the jsp - and correct my mistakes from step 2)
  • step 4) work out what the meta/javascript was that I needed for posting to the external system
  • note not quite finished step 4

Everything worked very quickly - took less than an hour, including reformating personDirectory.xml so that it was aligned and readable

Derek
University of Leeds, UK

Good to hear.  

I hope that Lum 5/Liferay is going to have a similar (or better) method for retrieving user session info.

Hi!

Thank you for this post! All of that works for me - I am able to pull and display different attributes from our external Sun One LDAP. However, I cannot pull an attribute that contains the password expiration time. This attribute must have some setting that makes it “invisible” since I cannot see it in an LDAP browser as well. It does show when I perform a command line query from one of our Luminis 4web machines. I am sure it should work, however, since our current Luminis 3 environment uses that same attribute, from the same server, accessing it with the same account in PersonDirs.xml and it works. I was wandering if anyone has had a similar problem and is willing to share a solution or an idea.

Thank you!

Vladimir Mollov

Vladimir,

We calculate that field based on pdsAccountCredentialChanged and your password expiration number of days (hard coded or use security.ias.password.max_days_lifespan). But, in LP4, I am still having issues rendering the CWEBProxy channel that worked just fine in LPIII. Maybe we can work on this together. Email me @ samir.ghorayeb@lamarpa.edu.

I have discovered that the reason why all password related attributes are not being pulled through personDirectory.xml. In Luminis 3 the logic that takes the attributes from PersonDirs.xml and generates the external LDAP request actually requests specifically these attributes.  In Luiminis 4 the request is for all atributes and then the ones in personDirectory.xml are picked from that response.  As a result, these "hidden" password related attributes are not brought in.

Does anyone know a way to make that request specify these particular attributes either through hacking the code that actually generates that request or through setting in personDirectory.xml (or ldap.xml) in LP4?

Any help on the subject is appreciated!

Vladimir Mollov

Thank you for all this information it has been very helpful.

In following the instructions on my LP4 box I don't have a webapp.xml file on my system.

Am I missing something?

Thanks,

Ryan Soward

You shouldn't need to edit webapp.xml unless I've forgotten something. The only file I mentioned in my post was personDirectory.xml (I did a quick re-read, so I may have missed it).

Hi Jason,

I've been trying to get your code to work with our test instance of Luminis and I keep getting errors. Could you tell me if your code works with Lum 4.2.3?

I added this to personDirectory.xml and restarted the server (several times!).

<entry key="pdsLoginId"><set><value>urn:sungardhe:dir:loginId</value><value>pdsLoginId</value></set></entry>

and my JSP looks like this:

<p><br /><br /><br /><br /></p> <p> private String getLoginId(HttpServletRequest hsr)<br /> throws PortalSecurityException<br /> {<br /> StringBuffer sb = new StringBuffer();<br /> SimplePersonManager spm = new SimplePersonManager();<br /> IPerson i = spm.getPerson(hsr);<br /> sb.append( (String)i.getAttribute("pdsLoginId"));<br /> return sb.toString();<br /> }<br /> %&gt;</p> <p><br /></p>

But, I get java.lang.NullPointerException

I am not sure what I did differently, but it seems to be working now. I can spit out the username at least! :)