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 %>" >
<% } %>
Comments
Alternative to editing personDirectory.xml
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.
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.