Customized authentication - overriding "getUserPrincipal() " 2004-02-04 - By Morten S. Mortensen
Back
All my custom authentication schemes are now operational! On both 4.1.29 and 5 .0.18.
I have had a real tough time, though. Apparently, the subject is complex, since no one here had any comment.
-- --
Together with custom authentication, I can also do HTTP content compression, override all input in the request like headers and the data to be read from the input-stream on the way down filter-chains and on the way back up the chains, I can read headers set upon the response, modify the content of the output-stream and do all sorts of tricks necessary for internal snooping, modification and filtering.
The custom authentication scheme can also co-exist with one of the usual schemes part of static servlet-configuration (though not desirable for anything but purposes of test).
To do these things, I have implemented two generic adapters - one for the request and one for the response. They both accept a number of plug-ins - a "HeaderResource" and a "ParameterResource", for instance - same concept like the "IdentityResource"-interface shown.
And yes, it does make a difference whether "request.getUserPrincipal()" or "super.getUserPrincipal()" is called - same for headers and so on for all public method of "HttpServletRequest" and "HttpServletResponse". Using "super" instead of "request" does do the trick!!!
The default wrappers have side-effects, which are necessary to invoke. I do not know which, because I have not looked.... Yet. I originally - and after a lot of thought - chose "request" instead, because this will per-construction avoid cyclic calls, should one of the methods from the interface "HttpServletRequest" be implemented in "HttpServletRequestWrapper" by invoking *another* of the interface-methods. It was intended to safe-guard me from "faulty" wrapper -implementations.
I sure hope, that the guys who implemented "javax.servlet.http .HttpServletRequestWrapper" and "HttpServletResponseWrapper" did a real good job . For each servlet-engine in existence.
If no interface-methods are implemented through other interface-methods, then everything will continue to work. If not, then trouble is ahead somewhere.
Within TC 4.1.29 and 5.0.18, the side-effects are necessary and the default -wrappers appears to be solid.
To those trying to implement generic wrappers with "plug-in" adapters, I can tell, that the Servlet-API is not just ideal - that would be so very sad to say -, since for instance headers can be accessed and modified in multiple ways, the input- and output-streams can both be accessed in two ways ("getInputStream ()", "getReader()" and "getOutputStream()", "getWriter()") - and so on. So very clumsy - nothing becomes simple. "HttpServletRequest" and "HttpServletResponse" are reasonable for direct access, but not for adaption - they should have been designed in at least two levels - one set for handling the protocol and one set for direct access - just like it is possible to control streams by implementing "InputStream" and "OutputStream", but have easy access by adapting them with "DataInputStream" and "DataOutputStream"........ Most certainly impossible to repair at this point in time.
Common API's are far from perfect.
-- --
Next time, please give me a hint.
Regards, Morten Sabroe Mortensen
-- --Original Message-- -- From: Morten S. Mortensen Sent: 3. februar 2004 20:09 To: tomcat-user@(protected) Cc: tomcat-dev-owner@(protected) Subject: Customized authentication - overriding "getUserPrincipal()"
Hi all,
I am in the process of testing some custom authentication schemes of my own. One thing, I would like, is to have "request.getUserPrincipal()" and "request .getAuthType()" return what I tell the request to return.
The "usual" way to grab and manipulate things is to write a filter (or servlet) , which wraps the incoming request and/or response and sends the wrapped versions down the filter-chain. One should suspect, that e.g. a wrapping of the request ends up in the request-objects accessible within JSP (possible wrapped again multiple times, depending upon the implementation of the engine) - so if I override "getUserPrincipal()" and "getAuthType()" and add a couple of setters "setUserPrincipal()" and "setAuthType()", I can control the result of "request .getUserPrincipal().getName()" and "request.getAuthType()".
This I have done.
Actually I created a kind of "plug-in"-object in the form of the interface shown below; it is supposed to include "isUserInRole()", too. The specializations of this interface have equivalent methods for setting the content to be returned. This "IdentityResource" plugs into the type of request -wrapper, which I create in a filter and use to invoke the filter-chain (of course a specialization of "javax.servlet.http.HttpServletRequestWrapper ").
*Apparently*, somewhere between my filter-chain - which implements the custom authentication scheme and wraps the request before invoking the filter-chain - and the actual JSP-pages, which I use as a test, the result og "getAuthType()" and "getUserPrincipal()" is lost; the two methods return 'null'.
This is somewhat of a disappointment.
Since I suspect, that Tomcat does something with the request in between the filter-chain and the JSP-page, I have looked a bit at the types. On the "main JSP page", which I invoke, the request is of type - "org.apache.coyote.tomcat4.CoyoteRequestFacade " - and on a sub-page included from the main page with <jsp:include>, the request is of type - "org.apache.catalina.core.ApplicationHttpRequest ". This has made me take a look at some of the source-code for this, but I can not find anything suspect, except that the top appears to.... not wrap the original request, but ends up in kind of a value-object...
Does something mess with the request before I hit the JSP-page-servlet-thingy? This realm-plugin-facility, which Tomcat has built in - it does not touch the request-object passed between filters and JSP-page-servlets?
Somehow it does not work. Maybe I have screwed something up in my code, but after a lot of investigation, I do not thing this is the case.
Anyone care to comment?
Who knows some details?
Anyone have tried something similar?
(yes, I now that the subject of "custom authentication schemes" within Servlets has been discussed, but postponed - but the construction, I try, should never the less be possible, if wrapping is done consistently)
? ? ?
Regards, Morten Sabroe Mortensen
-- --
/*** FILE "IdentityResource.java" *********************************************/
/******************************************************************************/ /** **/ /** 2003-10-28 Morten Sabroe Mortensen. **/ /** **/ /******************************************************************************/
/* * $Log$ */
package dk.tefs.J2EE.servlet.resource.http.identity;
import java.security.*; import java.util.*;
/*** IdentityResource: ********************************************************/
/** * Identification of a authenticated user. * * @(protected) <a href="mailto:Morten.Mortensen@(protected)" * >Morten Sabroe Mortensen</a> * @(protected) 1.0 */ public interface IdentityResource { /** * Gets the name of the authentication scheme used to protect * the requested resource. * @(protected) javax.servlet.http.HttpServletRequest #getAuthType * @(protected) Name of authentication scheme. */ String getAuthType();
/** * Indicates, whether the authenticated user is included in * a specified logical "role". * @(protected) javax.servlet.http.HttpServletRequest #isUserInRole * @(protected) role Logical role to get indication for. * @(protected) Indicates, if the role indicates the authenticated user. */ boolean isUserInRole(String role);
/** * Gets a representation of the authenticated user, if any. * If the user has not been authenticated, * this return <code>null</code>. * @(protected) javax.servlet.http.HttpServletRequest #getUserPrincipal * @(protected) Representation of the authenticated user. */ Principal getUserPrincipal();
/** * Gets the name of the authenticated user, if any. * @(protected) javax.servlet.http.HttpServletRequest #getRemoteUser * @(protected) Name of authenticated user. */ String getRemoteUser(); }
/******** "IdentityResource.java" *********************************************/
-- --
Fragment of "HttpServletRequestWrapper"-instance used to invoke filter-chain:
/** * Wrapped request. */ protected HttpServletRequest request;
/** * Alternative identity-resource. */ private IdentityResource identity;
/** * Sets the identity-resource. * @(protected) identity Identity-resource. */ public void setIdentityResource(IdentityResource identity) { this.identity=identity; }
/** * */ public Principal getUserPrincipal() { Principal res=null;
{ if (identity!=null) { res=identity.getUserPrincipal(); } else { res=request.getUserPrincipal(); //Note: It does a difference if 'super' or 'request' is called here! } }
return res; }
-- --
-- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ------ To unsubscribe, e-mail: tomcat-user-unsubscribe@(protected) For additional commands, e-mail: tomcat-user-help@(protected)
-- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ------ To unsubscribe, e-mail: tomcat-user-unsubscribe@(protected) For additional commands, e-mail: tomcat-user-help@(protected)
|
|