On Mon, 2008-09-15 at 12:53 -0700, Henrich Kraemer wrote: > > Lets consider an application which uses credentials similar to a web > browser: > 1. Credentials previously accepted by a server are automatically reused for > the same authentication scope. > 2. If a user gets prompted for credentials they are only remembered after > the server accepts them. The user can indicates to persist them beyond the > current session. > 3. Credentials which are not accepted by the server are invalidated and no > longer reused. They are removed from session state and/or the persisted > credential store. > > The application uses > - HttpClient 3. > - Multiple threads to execute HttpClient requests. All threads use a single > (global) HttpClient instance with a MultiThreadedHttpConnectionManager. > - a CredentialProvider to provide credentials. > > Consider a server which locks out users after receiving a bad password for > a particular user more than 3 consecutive times. > Now if the application uses 4 or more threads to access this server a user > can get locked out: > > Scenario 1) when the password has changed but HttpClient.state or the > CredentialProvider use old credentials. All threads send the old > credentials before noticing that they are no longer valid. I believe this > can happen even if the CredentialProvider provided them only once as other > threads will use the state of HttpState (I am looking at HttpClient 3.0 > code, but I believe this hasn't changed, looking at release notes) > (see org.apache.commons.httpclient.HttpMethodDirector.promptForCredentials > (AuthScheme, HttpParams, AuthScope)) > > Scenario 2) The user provides bad credentials but a correct username. The > provided credentials are stored in the HttpState associated with the > HttpClient instance. The other threads send the bad credentials as well > again picking them up via the HttpClient.state field. This would require a > good amount of bad luck, but I believe it might happen. > > I would think a solution would involve that concurrent requests requiring > the credentials for the same authentication scope would have to wait for > the server response before sending these credentials again (or refraining > from that and instead prompting again). This could be implemented by the > CredentialProvider. However the HttpState used in HttpClient 3 seems to > prevent this be without issues. On the other hand it might be useful for > many apps so perhaps it should be implemented by the framework and apps > responsibility would be limited to prompt users and store credentials. >
Hi Henrich, This is an inherent design issue. When requests are executed concurrently from multiple threads there is always a chance that enough requests get submitted in order to get the account locked before the application stands a change to react to the first authentication failure. The only way around this problem is serializing / synchronizing execution of requests. If you can live with occasional account lockouts, then you can execute a single request in order to validate the credentials and then proceed with executing more requests concurrently from multiple threads. > Is there a way for an application as sketched out to let HttpClient 3 > handle the authentication but avoid the lock out problem? > How would this be done using HttpClient 4? > > > An issue for an application which would implement this is to determine > whether provided credentials have been accepted by the server or not. In > HttpClient 3 one can assume that if the CredentialProvider is called that > any previously provided credentials were wrong. However the app can only > notice that it was accepted by waiting for HttpClient.executeMethod() to > return. However one would want to know as soon as possible to increase > concurrency. It seems that one would have to switch off redirection > handling. Unfortunately CredentialProvider stuff in HttpClient 3.x is fundamentally flawed. The idea of requesting new credentials in case of an authentication failure from inside the main execution loop was ill-conceived. > Has HttpClient 4 mechanism by which an application can determine as soon as > possible whether credentials used were accepted or rejected? > When using HttpClient 4.0 one is advised to do the following: * populate the credentials store with the default credentials if available * execute the request * if the request fails with status code 401 or 407, prompt the user for new credentials * update the credentials store according to the user input * retry One can also use the same logic with HttpClient 3.x. Hope this helps Oleg > Thanks, > > Henrich --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
