hc-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Adrian Sutton <adrian.sut...@ephox.com>
Subject RE: Using httpclient on the server to intercept and modify HTTP r esponse
Date Thu, 27 Feb 2003 00:00:43 GMT
Hi Chris,
HttpClient should be able to do everything you need it to, but you have hit
on one limitation that I've been meaning to fix for a long time now.
There's ways around it and if you pester me enough I might finally get
around to implementing it properly. :)  More below.

>1./ when connecting to something with the HTTPClient API, how do I
>dynamically which type of credentials I should use, if any?

You can always use NTCredentials as they extend UsernamePasswordCredentials,
this is the approach I take.  There is a definitely limitation in HttpClient
that it doesn't tell you what credentials it needs.  This is part 1 of the
stuff I've been meaning to do.  It should give you the Class for the
credentials type and there should be some way of knowing what parameters it
needs as well.

>2./ given that I'm forwarding requests from many clients via one host, are
>there any problems or pitfalls with multiple connections from that host
>using different credentials for each client?  is there any caching for
>example that might mean that the first NT login is used for some/all
>subsequent requests that should in fact be using the credentials for a
>different client?

That depends.  Credentials are stored per realm and are cached in the
HttpState instance for each HttpClient.  For NTLM, the domain name of the
server is used as the realm.  So if you have two users with different
credentials who attempt to access the same NTLM server, the credentials will
get mixed up.  You can (and should) however create a separate HttpState for
each client so that the credentials don't get mixed up too much and this
will also prevent cookies getting mixed up and a bunch of other stuff.

Laura has requested a version of executeMethod() in HttpClient that accepts
a specific state to use and that definitely seems like a good idea -
currently she is using the HttpMethod's directly and not using the
HttpClient class itself.  We'd like everyone to use the HttpClient class as
it makes development easier so I'm hoping that someone (possibly myself)
will look into the possibility of implementing that for 2.0.  It depends on
how complex it is though.

>3./ as I'll need to ask the client to provide credentials, I can either use
>a form or a BASIC authentification request.  If I limit the request to
>"username" and "password" fields, can I safely request that the client's
>username contains "DOMAIN\username" (and then decode it), as I'm not clear
>about where I should obtain domain names for?

You could take that approach, or you could use the nasty hack below to
detect if you're authenticating to NTLM or not and add a specific domain
field to your auth dialog/form.

The nasty hack to find out the realm to authenticate against and whether or
not you need a domain involves:
	  // If you might have to authenticate with proxies, don't forget to
check the
	  // Proxy-Authenticate header as well.
        String realm = get.getResponseHeader("WWW-Authenticate").getValue();
        boolean isNTLM = (realm != null &&
realm.toLowerCase().indexOf("ntlm") >= 0);
        String tmpRealm;
        if (isNTLM) {
            if (proxy) {
                tmpRealm = client.getProxyHost();
            } else {
                tmpRealm = src.getHost();
        } else {
            tmpRealm = parseRealmFromChallenge(realm);
	  // isNTLM now stores whether or not you need to get a domain from
the user as well.
	  // tmpRealm now contains the name of the realm you're
authenticating against.

    // Blantantly ripped from HttpClient's Authenticator.java  You may want
to check for updates.
    private String parseRealmFromChallenge(String challenge) {
        log.trace("enter parseRealmFromChallenge(String challenge)");
        try {
            StringTokenizer strtok = new StringTokenizer(challenge, "=");
            String realm = strtok.nextToken().trim();
            int firstq = realm.indexOf('"');
            int lastq = realm.lastIndexOf('"');

            if ((firstq + 1) < lastq) {
                realm = realm.substring(firstq + 1, lastq);

            return realm;
        } catch (Exception ex) {
            System.err.println("Failed to parse realm: " + challenge + " - "
+ ex.getMessage());
            return null;

Hope that helps....

Adrian Sutton, Software Engineer
Ephox Corporation

View raw message