Re: Re: Loadbalancing with NTLMServlet/Filter

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

Re: Re: Loadbalancing with NTLMServlet/Filter

Smyth, Jim
Hi,

I experienced an issue with using jcifs on applications running across multiple app servers which I found reported some time ago (see below).  I believe the end solution may not be correct.  To recap (and fully explain) the issue, the 401 Authenticate response created by JCIFS filter tells the browser to resend the same request with NTLM credentials.  When a user first hits an application a session is automatically created for that user.  Normally all subsequent requests by that user will use a session identifier (via URL-rewriting or a cookie) to maintain the state of the application.  All quite simple so far.

An issue arises when an application is running on multiple processes rather than just multiple threads, because the 401 which makes the browser resend a request may end up at a different running process which will invalidate the NTLM negociation mechanism.  Running an application over a number of machines is one way in which this situation arises, but the big boys from weblogic and WAS also recognize that scaling appservers on threads only goes so far, such that multi-process appservers on single (big) boxes also exist.

Anyway, Im sure you know all that.  The point is that

a)  the session is implicitly created at the outset, therefore, calling req.getSession() as originally suggested will not have any effect
b)  to avoid this issue the servlet filter should start with something like the following so that negociate will never commence until we can be sure the authorization will be sent back to the correct appserver process:

                        if (Config.getProperty("jcifs.util.multiProcess")!=null && Config.getProperty("jcifs.util.multiProcess").equals("true")) {  //check if defined as multi-process appserver
                                //this code should only ever get executed once per user per session
                                if (session.getAttribute("NTLMNegociationInitiated")==null) {
                                        session.setAttribute("NTLMNegociationInitiated","true");
                                       
                                        //should be a block of code here responsible for setting a cookie if cookie based session management is in use
                                        //but I havent bothered doing that yet
                                        //...

                                        //the following code will take care of urlrewriting if required
                                PrintWriter out = null;
                                        out = resp.getWriter();
                                out.println("<html>");
                                out.println("<head>");
                                out.println("<title>Resending request with Session id</title>");
                                out.println("<META Http-Equiv=\"Cache-Control\" Content=\"no-cache\">");
                                out.println("<META Http-Equiv=\"Pragma\" Content=\"no-cache\">");
                                out.println("<META Http-Equiv=\"Expires\" Content=\"0\">");
                                out.println("<meta http-equiv=\"refresh\" content=\"0; URL=" + resp.encodeURL(req.getRequestURL().toString()) + "\">");
                                out.println("</head>");
                                    out.println("</html>");
                                    return;
                                } //end if
                        } //end of check for multi-process appserver



Anyways - thats the way I would (will) do it.  Hope its of use/interest.

rgds
jim




From: Eric <eglass1 <at> comcast.net>
Subject: Re: Re: Loadbalancing with NTLMServlet/Filter <http://news.gmane.org/find-root.php?message_id=%3c405B99A2.2090403%40comcast.net%3e>
Date: 2004-03-20 01:08:50 GMT (1 year, 35 weeks, 2 days, 17 hours and 16 minutes ago)

He's load balancing the servlet containers (application servers); he's
got a single web server with multiple WebSphere containers on the back
end.  The connector on the web server uses the session ID to determine
which application server the request gets routed to.  We don't currently
create a session until the NTLM handshake has completed (when we store
the username etc. in the session).  So what he's seeing is server A
generates the challenge and sends the Type 2 message, but server B ends
up getting the Type 3 message (the HTTP keepalive is between the client
and the web server, but not between the web server and a particular
application server).

Creating the session at the outset would prevent this (and is probably
an appropriate measure).

Eric

Michael B Allen wrote:

> I don't see what this has to do with load balancing. Please send your
> precise suggested fix to the jcifs mailing list.
>
> Sylwester Lachiewicz said:
>
>>Hi,
>>
>>With current NtlmServletFilter it's not possible to create application
>>with loadbalancing
>>Our http server  (IBM HTTP with WebSphere plugin) use session cookie to
>>route requests to one of our Application Server. Becouse full NTLM Auth
>>requires 3 resuests/responses it's possible that one request will be
>>received by AppServer1 and second with AppServer2. This creates auth
>>failure.
>>
>>To fix this, in service method, i add line request.getSession() so session
>>will be created and JSESSIONID returned to browser and available to next
>>requests.
>>It's possible to add this to NtlmServlet and NtlmFilter?
>>
>>S.
>>
>
>
>


> Jim Smyth
> BVGS
>
> Mobile +44 (0) 7720 352 014
>
> BroadVision
> Energizing e-Business
>
>
> This message is intended only for the use of the Addressee and may contain information that is PRIVILEGED and CONFIDENTIAL.  If you are not the intended recipient, dissemination of this communication is prohibited.  If you have received this communication in error, please erase all copies of the message and its attachments and notify us immediately.
>