Subversion Repositories javautils

Rev

Blame | Last modification | View Log | RSS feed

  1. <html><head>
  2.       <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
  3.    <title>Chapter&nbsp;4.&nbsp;HTTP authentication</title><link rel="stylesheet" href="css/hc-tutorial.css" type="text/css"><meta name="generator" content="DocBook XSL-NS Stylesheets V1.73.2"><link rel="start" href="index.html" title="HttpClient Tutorial"><link rel="up" href="index.html" title="HttpClient Tutorial"><link rel="prev" href="statemgmt.html" title="Chapter&nbsp;3.&nbsp;HTTP state management"><link rel="next" href="httpagent.html" title="Chapter&nbsp;5.&nbsp;HTTP client service"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div xmlns:fo="http://www.w3.org/1999/XSL/Format" class="banner"><a class="bannerLeft" href="http://www.apache.org/" title="Apache Software Foundation"><img style="border:none;" src="images/asf_logo_wide.gif"></a><a class="bannerRight" href="http://hc.apache.org/httpcomponents-core/" title="Apache HttpComponents Core"><img style="border:none;" src="images/hc_logo.png"></a><div class="clear"></div></div><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Chapter&nbsp;4.&nbsp;HTTP authentication</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="statemgmt.html">Prev</a>&nbsp;</td><th width="60%" align="center">&nbsp;</th><td width="20%" align="right">&nbsp;<a accesskey="n" href="httpagent.html">Next</a></td></tr></table><hr></div><div class="chapter" lang="en"><div class="titlepage"><div><div><h2 class="title"><a name="authentication"></a>Chapter&nbsp;4.&nbsp;HTTP authentication</h2></div></div></div>
  4.    
  5.     <p>HttpClient provides full support for authentication schemes defined by the HTTP standard
  6.         specification. HttpClient's authentication framework can also be extended to support
  7.        non-standard authentication schemes such as <code class="literal">NTLM</code> and
  8.            <code class="literal">SPNEGO</code>.</p>
  9.    <div class="section" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d4e829"></a>4.1.&nbsp;User credentials</h2></div></div></div>
  10.        
  11.        <p>Any process of user authentication requires a set of credentials that can be used to
  12.            establish user identity. In the simplest form user crednetials can be just a user name /
  13.            password pair. <code class="classname">UsernamePasswordCredentials</code> represents a set of
  14.            credentials consisting of a security principal and a password in clear text. This
  15.            implementation is sufficient for standard authentication schemes defined by the HTTP
  16.            standard specification.</p>
  17.        <pre class="programlisting">
  18. UsernamePasswordCredentials creds = new UsernamePasswordCredentials("user", "pwd");
  19. System.out.println(creds.getUserPrincipal().getName());
  20. System.out.println(creds.getPassword());
  21.        </pre>
  22.        <p>stdout &gt;</p>
  23.        <pre class="programlisting">
  24. user
  25. pwd
  26. </pre>
  27.        <p><code class="classname">NTCredentials</code> is a Microsoft Windows specific implementation
  28.            that includes in addition to the user name / password pair a set of additional Windows
  29.            specific attributes such as a name of the user domain, as in Microsoft Windows network
  30.            the same user can belong to multiple domains with a different set of
  31.            authorizations.</p>
  32.        <pre class="programlisting">
  33. NTCredentials creds = new NTCredentials("user", "pwd", "workstation", "domain");
  34. System.out.println(creds.getUserPrincipal().getName());
  35. System.out.println(creds.getPassword());
  36. </pre>
  37.        <p>stdout &gt;</p>
  38.        <pre class="programlisting">
  39. DOMAIN/user
  40. pwd
  41. </pre>
  42.    </div>
  43.    <div class="section" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d4e841"></a>4.2.&nbsp;Authentication schemes</h2></div></div></div>
  44.        
  45.        <p>The <code class="interfacename">AuthScheme</code> interface represents an abstract
  46.            challenge-response oriented authentication scheme. An authentication scheme is expected
  47.            to support the following functions:</p>
  48.        <div class="itemizedlist"><ul type="disc"><li>
  49.                <p>Parse and process the challenge sent by the target server in response to
  50.                    request for a protected resource.</p>
  51.            </li><li>
  52.                <p>Provide properties of the processed challenge: the authentication scheme type
  53.                    and its parameters, such the realm this authentication scheme is applicable to,
  54.                    if available</p>
  55.            </li><li>
  56.                <p>Generate authorization string for the given set of credentials and the HTTP
  57.                    request in response to the actual authorization challenge.</p>
  58.            </li></ul></div>
  59.        <p>Please note authentication schemes may be stateful involving a series of
  60.            challenge-response exchanges.</p>
  61.        <p>HttpClient ships with several <code class="interfacename">AuthScheme</code>
  62.            implementations:</p>
  63.        <div class="itemizedlist"><ul type="disc"><li>
  64.                <p>
  65.                    <b>Basic:&nbsp;</b>
  66.                    Basic authentication scheme as defined in RFC 2617. This authentication
  67.                        scheme is insecure, as the credentials are transmitted in clear text.
  68.                        Despite its insecurity Basic authentication scheme is perfectly adequate if
  69.                        used in combination with the TLS/SSL encryption.
  70.                </p>
  71.            </li><li>
  72.                <p>
  73.                    <b>Digest.&nbsp;</b>
  74.                    Digest authentication scheme as defined in RFC 2617. Digest authentication
  75.                        scheme is significantly more secure than Basic and can be a good choice for
  76.                        those applications that do not want the overhead of full transport security
  77.                        through TLS/SSL encryption.
  78.                </p>
  79.            </li><li>
  80.                <p>
  81.                    <b>NTLM:&nbsp;</b>
  82.                    NTLM is a proprietary authentication scheme developed by Microsoft and
  83.                        optimized for Windows platforms. NTLM is believed to be more secure than
  84.                        Digest. This scheme is requires an external NTLM engine to be functional.
  85.                        For details please refer to the <code class="literal">NTLM_SUPPORT.txt</code> document
  86.                        included with HttpClient distributions.
  87.                </p>
  88.            </li></ul></div>
  89.    </div>
  90.    <div class="section" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d4e869"></a>4.3.&nbsp;HTTP authentication parameters</h2></div></div></div>
  91.        
  92.        <p>These are parameters that be used to customize HTTP authentication process and
  93.            behaviour of individual authentication schemes:</p>
  94.        <div class="itemizedlist"><ul type="disc"><li>
  95.                <p>
  96.                    <b>'http.protocol.handle-authentication':&nbsp;</b>
  97.                    defines whether authentication should be handled automatically. This
  98.                        parameter expects a value of type <code class="classname">java.lang.Boolean</code>.
  99.                        If this parameter is not set HttpClient will handle authentication
  100.                        automatically.
  101.                </p>
  102.            </li><li>
  103.                <p>
  104.                    <b>'http.auth.credential-charset':&nbsp;</b>
  105.                    defines the charset to be used when encoding user credentials. This
  106.                        parameter expects a value of type <code class="literal">java.lang.String</code>. If
  107.                        this parameter is not set <code class="literal">US-ASCII</code> will be used.
  108.                </p>
  109.            </li></ul></div>
  110.    </div>
  111.    <div class="section" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d4e884"></a>4.4.&nbsp;Authentication scheme registry</h2></div></div></div>
  112.        
  113.        <p>HttpClient maintains a registry of available authentication scheme using
  114.                <code class="classname">AuthSchemeRegistry</code> class. The following schemes are
  115.            registered per default:</p>
  116.        <div class="itemizedlist"><ul type="disc"><li>
  117.                <p>
  118.                    <b>Basic:&nbsp;</b>
  119.                    Basic authentication scheme
  120.                </p>
  121.            </li><li>
  122.                <p>
  123.                    <b>Digest:&nbsp;</b>
  124.                    Digest authentication scheme
  125.                </p>
  126.            </li></ul></div>
  127.        <p>Please note <code class="literal">NTLM</code> scheme is <span class="emphasis"><em>NOT</em></span> registered per
  128.            default. The <code class="literal">NTLM</code> cannot be enabled per default due to licensing and
  129.            legal reasons. For details on how to enable <code class="literal">NTLM</code> support please see
  130.            <a class="link" href="authentication.html#ntlm" title="4.8.&nbsp;NTLM Authentication">this</a> section. </p>
  131.    </div>
  132.    <div class="section" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d4e903"></a>4.5.&nbsp;Credentials provider</h2></div></div></div>
  133.        
  134.        <p>Credentials providers are intended to maintain a set of user credentials and to be
  135.            able to produce user credentials for a particular authentication scope. Authentication
  136.            scope consists of a host name, a port number, a realm name and an authentication scheme
  137.            name. When registering credentials with the credentials provider one can provide a wild
  138.            card (any host, any port, any realm, any scheme) instead of a concrete attribute value.
  139.            The credentials provider is then expected to be able to find the closest match for a
  140.            particular scope if the direct match cannot be found.</p>
  141.        <p>HttpClient can work with any physical representation of a credentials provider that
  142.            implements the <code class="interfacename">CredentialsProvider</code> interface. The default
  143.                <code class="interfacename">CredentialsProvider</code> implementation called
  144.                <code class="classname">BasicCredentialsProvider</code> is a simple implementation backed by
  145.            a <code class="classname">java.util.HashMap</code>.</p>
  146.        <pre class="programlisting">
  147. CredentialsProvider credsProvider = new BasicCredentialsProvider();
  148. credsProvider.setCredentials(
  149.    new AuthScope("somehost", AuthScope.ANY_PORT),
  150.    new UsernamePasswordCredentials("u1", "p1"));
  151. credsProvider.setCredentials(
  152.    new AuthScope("somehost", 8080),
  153.    new UsernamePasswordCredentials("u2", "p2"));
  154. credsProvider.setCredentials(
  155.    new AuthScope("otherhost", 8080, AuthScope.ANY_REALM, "ntlm"),
  156.    new UsernamePasswordCredentials("u3", "p3"));
  157.  
  158. System.out.println(credsProvider.getCredentials(
  159.    new AuthScope("somehost", 80, "realm", "basic")));
  160. System.out.println(credsProvider.getCredentials(
  161.    new AuthScope("somehost", 8080, "realm", "basic")));
  162. System.out.println(credsProvider.getCredentials(
  163.    new AuthScope("otherhost", 8080, "realm", "basic")));
  164. System.out.println(credsProvider.getCredentials(
  165.    new AuthScope("otherhost", 8080, null, "ntlm")));
  166. </pre>
  167.        <p>stdout &gt;</p>
  168.        <pre class="programlisting">
  169. [principal: u1]
  170. [principal: u2]
  171. null
  172. [principal: u3]
  173. </pre>
  174.    </div>
  175.    <div class="section" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d4e914"></a>4.6.&nbsp;HTTP authentication and execution context</h2></div></div></div>
  176.        
  177.        <p>HttpClient relies on the <code class="classname">AuthState</code> class to keep track of
  178.            detailed information about the state of the authentication process. HttpClient creates
  179.            two instances of <code class="classname">AuthState</code> in the course of HTTP request
  180.            execution: one for target host authentication and another one for proxy authentication.
  181.            In case the target server or the proxy require user authentication the respective
  182.                <code class="classname">AuthScope</code> instance will be populated with the
  183.                <code class="classname">AuthScope</code>, <code class="interfacename">AuthScheme</code> and
  184.                <code class="interfacename">Crednetials</code> used during the authentication process.
  185.            The <code class="classname">AuthState</code> can be examined in order to find out what kind of
  186.            authentication was requested, whether a matching
  187.                <code class="interfacename">AuthScheme</code> implementation was found and whether the
  188.            credentials provider managed to find user credentials for the given authentication
  189.            scope.</p>
  190.        <p>In the course of HTTP request execution HttpClient adds the following authentication
  191.            related objects to the execution context:</p>
  192.        <div class="itemizedlist"><ul type="disc"><li>
  193.                <p>
  194.                    <b>'http.authscheme-registry':&nbsp;</b>
  195.                    <code class="classname">AuthSchemeRegistry</code> instance representing the actual
  196.                        authentication scheme registry. The value of this attribute set in the local
  197.                        context takes precedence over the default one.
  198.                </p>
  199.            </li><li>
  200.                <p>
  201.                    <b>'http.auth.credentials-provider':&nbsp;</b>
  202.                    <code class="interfacename">CookieSpec</code> instance representing the actual
  203.                        credentials provider. The value of this attribute set in the local context
  204.                        takes precedence over the default one.
  205.                </p>
  206.            </li><li>
  207.                <p>
  208.                    <b>'http.auth.target-scope':&nbsp;</b>
  209.                    <code class="classname">AuthState</code> instance representing the actual target
  210.                        authentication state. The value of this attribute set in the local context
  211.                        takes precedence over the default one.
  212.                </p>
  213.            </li><li>
  214.                <p>
  215.                    <b>'http.auth.proxy-scope':&nbsp;</b>
  216.                    <code class="classname">AuthState</code> instance representing the actual proxy
  217.                        authentication state. The value of this attribute set in the local context
  218.                        takes precedence over the default one.
  219.                </p>
  220.            </li></ul></div>
  221.        <p>The local <code class="interfacename">HttpContext</code> object can be used to customize
  222.            the HTTP authentication context prior to request execution or examine its state after
  223.            the request has been executed:</p>
  224.        <pre class="programlisting">
  225. HttpClient httpclient = new DefaultHttpClient();
  226. HttpContext localContext = new BasicHttpContext();
  227. HttpGet httpget = new HttpGet("http://localhost:8080/");
  228. HttpResponse response = httpclient.execute(httpget, localContext);
  229.  
  230. AuthState proxyAuthState = (AuthState) localContext.getAttribute(
  231.    ClientContext.PROXY_AUTH_STATE);
  232. System.out.println("Proxy auth scope: " + proxyAuthState.getAuthScope());
  233. System.out.println("Proxy auth scheme: " + proxyAuthState.getAuthScheme());
  234. System.out.println("Proxy auth credentials: " + proxyAuthState.getCredentials());
  235. AuthState targetAuthState = (AuthState) localContext.getAttribute(
  236.    ClientContext.TARGET_AUTH_STATE);
  237. System.out.println("Target auth scope: " + targetAuthState.getAuthScope());
  238. System.out.println("Target auth scheme: " + targetAuthState.getAuthScheme());
  239. System.out.println("Target auth credentials: " + targetAuthState.getCredentials());
  240. </pre>
  241.    </div>
  242.    <div class="section" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d4e950"></a>4.7.&nbsp;Preemptive authentication</h2></div></div></div>
  243.        
  244.        <p>HttpClient does not support preemptive authentication out of the box, because if
  245.            misused or used incorrectly the preemptive authentication can lead to significant
  246.            security issues, such as sending user credentials in clear text to an unauthorized third
  247.            party. Therefore, users are expected to evaluate potential benefits of preemptive
  248.            authentication versus security risks in the context of their specific application
  249.            environment and are required to add support for preemptive authentication using standard
  250.            HttpClient extension mechanisms such as protocol interceptors.</p>
  251.        <p>This is an example of a simple protocol interceptor that preemptively introduces an
  252.            instance of <code class="classname">BasicScheme</code> to the execution context, if no
  253.            authentication has been attempted yet. Please note that this interceptor must be added
  254.            to the protocol processing chain before the standard authentication interceptors.</p>
  255.        <pre class="programlisting">
  256. HttpRequestInterceptor preemptiveAuth = new HttpRequestInterceptor() {
  257.    
  258.    public void process(
  259.            final HttpRequest request,
  260.            final HttpContext context) throws HttpException, IOException {
  261.        
  262.        AuthState authState = (AuthState) context.getAttribute(
  263.                ClientContext.TARGET_AUTH_STATE);
  264.        CredentialsProvider credsProvider = (CredentialsProvider) context.getAttribute(
  265.                ClientContext.CREDS_PROVIDER);
  266.        HttpHost targetHost = (HttpHost) context.getAttribute(
  267.                ExecutionContext.HTTP_TARGET_HOST);
  268.        
  269.        // If not auth scheme has been initialized yet
  270.        if (authState.getAuthScheme() == null) {
  271.            AuthScope authScope = new AuthScope(
  272.                    targetHost.getHostName(),
  273.                    targetHost.getPort());
  274.            // Obtain credentials matching the target host
  275.            Credentials creds = credsProvider.getCredentials(authScope);
  276.            // If found, generate BasicScheme preemptively
  277.            if (creds != null) {
  278.                authState.setAuthScheme(new BasicScheme());
  279.                authState.setCredentials(creds);
  280.            }
  281.        }
  282.    }
  283.    
  284. };
  285.  
  286. DefaultHttpClient httpclient = new DefaultHttpClient();
  287. // Add as the very first interceptor in the protocol chain
  288. httpclient.addRequestInterceptor(preemptiveAuth, 0);
  289. </pre>
  290.    </div>
  291.  
  292.    <div class="section" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="ntlm"></a>4.8.&nbsp;NTLM Authentication</h2></div></div></div>
  293.        
  294.        <p>Currently HttpClient does not provide support for the NTLM authentication scheme out
  295.            of the box and probably never will. The reasons for that are legal rather than
  296.            technical. However, NTLM authentication can be enabled by using an external
  297.            <code class="literal">NTLM</code> engine such as <a class="ulink" href="http://jcifs.samba.org/" target="_top">JCIFS
  298.            </a> library developed by the <a class="ulink" href="http://www.samba.org/" target="_top">Samba</a>
  299.            project as a part of their Windows interoperability suite of programs. For details
  300.            please refer to the <code class="literal">NTLM_SUPPORT.txt</code> document included with
  301.            HttpClient distributions.
  302.        </p>
  303.        <div class="section" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="d4e963"></a>4.8.1.&nbsp;NTLM connection persistence</h3></div></div></div>
  304.            
  305.            <p><code class="literal">NTLM</code> authentication scheme is significantly more expensive
  306.                in terms of computational overhead and performance impact than the standard
  307.                <code class="literal">Basic</code> and <code class="literal">Digest</code> schemes. This is likely to be
  308.                one of the main reasons why Microsoft chose to make <code class="literal">NTLM</code>
  309.                authentication scheme stateful. That is, once authenticated, the user identity is
  310.                associated with that connection for its entire life span. The stateful nature of
  311.                <code class="literal">NTLM</code> connections makes connection persistence more complex, as
  312.                for the obvious reason persistent <code class="literal">NTLM</code> connections may not be
  313.                re-used by users with a different user identity. The standard connection managers
  314.                shipped with HttpClient are fully capable of managing stateful connections. However,
  315.                it is critically important that logically related requests within the same session
  316.                use the same execution context in order to make them aware of the current user
  317.                identity. Otherwise, HttpClient will end up creating a new HTTP connection for each
  318.                HTTP request against <code class="literal">NTLM</code> protected resources. For detailed
  319.                discussion on stateful HTTP connections please refer to
  320.                <a class="link" href="advanced.html#stateful_conn" title="6.2.&nbsp;Stateful HTTP connections">this </a> section. </p>
  321.            <p>As <code class="literal">NTLM</code> connections are stateful it is generally recommended
  322.                to trigger <code class="literal">NTLM</code> authentication using a relatively cheap method,
  323.                such as <code class="literal">GET</code> or <code class="literal">HEAD</code>, and re-use the same
  324.                connection to execute more expensive methods, especially those enclose a request
  325.                entity, such as <code class="literal">POST</code> or <code class="literal">PUT</code>. </p>
  326.            <pre class="programlisting">
  327. DefaultHttpClient httpclient = new DefaultHttpClient();
  328.  
  329. NTCredentials creds = new NTCredentials("user", "pwd", "myworkstation", "microsoft.com");
  330. httpclient.getCredentialsProvider().setCredentials(AuthScope.ANY, creds);
  331.  
  332. HttpHost target = new HttpHost("www.microsoft.com", 80, "http");
  333.  
  334. // Make sure the same context is used to execute logically related requests
  335. HttpContext localContext = new BasicHttpContext();
  336.  
  337. // Execute a cheap method first. This will trigger NTLM authentication
  338. HttpGet httpget = new HttpGet("/ntlm-protected/info");
  339. HttpResponse response1 = httpclient.execute(target, httpget, localContext);
  340. HttpEntity entity1 = response1.getEntity();
  341. if (entity1 != null) {
  342.    entity1.consumeContent();
  343. }
  344.  
  345. // Execute an expensive method next reusing the same context (and connection)
  346. HttpPost httppost = new HttpPost("/ntlm-protected/form");
  347. httppost.setEntity(new StringEntity("lots and lots of data"));
  348. HttpResponse response2 = httpclient.execute(target, httppost, localContext);
  349. HttpEntity entity2 = response2.getEntity();
  350. if (entity2 != null) {
  351.    entity2.consumeContent();
  352. }
  353. </pre>
  354.        </div>
  355.    </div>
  356.  
  357. </div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="statemgmt.html">Prev</a>&nbsp;</td><td width="20%" align="center">&nbsp;</td><td width="40%" align="right">&nbsp;<a accesskey="n" href="httpagent.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Chapter&nbsp;3.&nbsp;HTTP state management&nbsp;</td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top">&nbsp;Chapter&nbsp;5.&nbsp;HTTP client service</td></tr></table></div></body></html>