LDAP Logon and Password Management (part 2)
This is in continuation of my previous post. The PostLogonFilter Well today I am starting up with the filters. So I added the necessary entries to my web.xml file now. As I was writing it, I think I would be creating a separate java only project soon so I can keep the web app as customizable as possible. But for now all will be in the same project. So the PostLogonFilter would be mapped against /j_security_check and it will be invoked on a successful run of the validation. I was thinking of putting in a JUnit test to validate this, but I don't really know how to verify j_security_check on HttpUnit. Oh well, the app is very simple I think it would be way too overkill to automate the unit test on this one. Ugh, I feel dirty just saying that. Of course since you are going to be using servlet API, you really should include the javax.servlet servlet-api dependency. Grr, they should add that to the archetype as well. When I finish with this I am going to be writing a patch for that webapp archetype. Apparently I am using version 2.4 of the servlet API not the one I originally intended. I love maven, just one switch on the POM and poof we're on version 2.4 now. For now I put in a System.out in the filter, but I didn't see it on the console. I think it is because the jetty just eats it up. So I registered commons-logging and put in the message using commons logging. But that still didn't work. Found out the reason. j_security_check filters only work on WebSphere. Fortunately for me that is my target platform. Unfortunately I have no way of testing without deploying to that platform, I'd rather use Jetty because of speed. Anyway I used the Listener instead. Yes it is not ideal because it will get invoked for every request, but since the application is small and simple it shouldn't be too too bad.
public void requestDestroyed(final ServletRequestEvent sre) {
final HttpServletRequest httpServletRequest = (HttpServletRequest) sre
.getServletRequest();
String mapping = httpServletRequest.getRequestURI().substring(
httpServletRequest.getContextPath().length());
if ("/j_security_check".equals(mapping)
&& httpServletRequest.getUserPrincipal() != null) {
System.err.println("yo " +
httpServletRequest.getUserPrincipal().getName());
}
}Is what I put in my code. Seems to work, getting the mapping is going to be a bit slow, but I'll work on optimizing it later.
I will be changing the "yo" message with the expiration checks in a bit.
However, all of the above does not work well. So how do I do it now?
Well I made a Servlet that does the login instead, but forwards to j_security_check.
The LogonServlet
The logon servlet works suprisingly well. Of course it means that you have to use a non-standard servlet rather than j_security_check, but so what? Really it does not matter since this is a separate application and we can customize it as much as we want.
So here is how it flows:
Checking for expiration of passwords
I took some concepts from a devWorks article on how to do this and for the most part it is fine, except that the netscape packages are not in an obvious place. However, I did find the Netscape LDAP SDK eventually and things just worked out for the best from that point.
One gotcha that you have to note is when you reset the password, it will not expire in Tivoli, but rather it will return an error when you try to login. So rather than calling the method "check if password expired", I basically called it "checkPasswordChangeRequired"
Further work
Once I got the main flows all worked out, I just put struts around it to make the UI code more cleaner rather than having a lot of spaghetti JSP and servlets with embedded Java code. It also supports i18n when we have to port it to French. However, I am not going to cover that topic.
