mbecke 2003/06/11 20:31:50
Modified: httpclient/xdocs navigation.xml
Added: httpclient/xdocs sslguide.xml
Log:
Added SSL Guide.
PR: 10809
Submitted by: Oleg Kalnichevski
Revision Changes Path
1.8 +2 -1 jakarta-commons/httpclient/xdocs/navigation.xml
Index: navigation.xml
===================================================================
RCS file: /home/cvs/jakarta-commons/httpclient/xdocs/navigation.xml,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- navigation.xml 1 Jun 2003 18:51:23 -0000 1.7
+++ navigation.xml 12 Jun 2003 03:31:50 -0000 1.8
@@ -24,6 +24,7 @@
<item name="Logging Guide" href="/logging.html"/>
<item name="Methods" href="/methods.html"/>
<item name="Sample Code"
href="http://cvs.apache.org/viewcvs/jakarta-commons/httpclient/src/examples/"/>
+ <item name="SSL Guide" href="/sslguide.html"/>
<item name="Threading" href="/threading.html"/>
<item name="Trouble Shooting" href="/troubleshooting.html"/>
<item name="Tutorial" href="/tutorial.html"/>
1.1 jakarta-commons/httpclient/xdocs/sslguide.xml
Index: sslguide.xml
===================================================================
<?xml version="1.0" encoding="ISO-8859-1"?>
<document>
<properties>
<title>HttpClient SSL Guide</title>
<author email="[EMAIL PROTECTED]">Oleg Kalnichevski</author>
<revision>$Id: sslguide.xml,v 1.1 2003/06/12 03:31:50 mbecke Exp $</revision>
</properties>
<body>
<section name="Introduction">
<p>
HttpClient provides full support for HTTP over Secure Sockets Layer (SSL) or
IETF Transport Layer
Security (TLS) protocols by leveraging the <a
href="http://java.sun.com/products/jsse/index.html">
Java Secure Socket Extension (JSSE)</a>. JSSE has been integrated into the
Java 2 platform as of
version 1.4 and usually should work with HttpClient out of the box. On older
Java 2 versions JSSE
needs to be manually installed and configured. Installation instructions can
be found
<a
href="http://java.sun.com/products/jsse/doc/guide/API_users_guide.html#Installation">here</a>
</p>
</section>
<section name="Standard SSL in HttpClient">
<p>
With SSL properly set up and configured, secure HTTP communication over SSL
should be as simple
as plain HTTP communication.
</p>
<source><![CDATA[
HttpClient httpclient = new HttpClient();
GetMethod httpget = new GetMethod("https://www.verisign.com/");
httpclient.executeMethod(httpget);
System.out.println(httpget.getStatusLine().toString());
]]></source>
<p>
HTTPS communication via an authenticating proxy server is also no different
from plain HTTP
communication. All the low-level details of establishing a tunneled SSL
connection are abstracted
away by HttpClient:
</p>
<source><![CDATA[
HttpClient httpclient = new HttpClient();
httpclient.getHostConfiguration().setProxy("myproxyhost", 8080);
httpclient.getState().setProxyCredentials("my-proxy-realm", " myproxyhost",
new UsernamePasswordCredentials("my-proxy-username", "my-proxy-password"));
GetMethod httpget = new GetMethod("https://www.verisign.com/");
httpclient.executeMethod(httpget);
System.out.println(httpget.getStatusLine().toString());
]]></source>
</section>
<section name="Customizing SSL in HttpClient">
<p>
Per default HTTP client does not perform any custom certificate or
certificate chain validation.
The default HTTPS protocol implementation is completely reliant upon the
standard functionality
of the JSSE that comes with the JVM. If your application requires some
additional processing of
credentials such certificate verification or certificate chain validation, or
you want to be using
a third party SSL library, you can augment HttpClient to meet your specific
requirements by providing
a custom protocol implementation.
</p>
<p>
Implementation of a custom protocol involves the following steps:
</p>
<ul>
<li>
<p>
Provide a custom socket factory that implements
<a
href="apidocs/org/apache/commons/httpclient/protocol/SecureProtocolSocketFactory.html">
org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory</a>
interface. The socket
factory should encapsulate application specific aspects of opening a socket
to the target server
using either standard or third party SSL library.
</p>
</li>
<li>
<p>
Instantiate an object of type <a
href="apidocs/org/apache/commons/httpclient/protocol/Protocol.html">
org.apache.commons.httpclient.protocol.Protocol</a>. The new instance would
be initialized with the
following parameters: valid URI protocol scheme (https in this case),
custom socket factory discussed
above, and a default port number.
</p>
<source><![CDATA[
Protocol myhttps = new Protocol("https", new MySSLSocketFactory(), 443);
]]></source>
<p>
The resultant protocol object then can be used as a default protocol for a
host.
</p>
<source><![CDATA[
HttpClient httpclient = new HttpClient();
httpclient.getHostConfiguration().setHost("www.whatever.com", 443, myhttps);
GetMethod httpget = new GetMethod("/");
httpclient.executeMethod(httpget);
]]></source>
</li>
<li>
<p>
Optionally register the custom protocol by calling
Protocol.registerProtocol method. You can
specify your own protocol designator (such as 'myhttps') if you are going
to be using this protocol
along with the default SSL protocol implementation.
</p>
<source><![CDATA[
Protocol.registerProtocol("myhttps",
new Protocol("https", new MySSLSocketFactory(), 9443));
]]></source>
<p>
Once registered the protocol be used as a 'virtual' scheme inside target
URIs.
</p>
<source><![CDATA[
HttpClient httpclient = new HttpClient();
GetMethod httpget = new GetMethod("myhttps://www.whatever.com/");
httpclient.executeMethod(httpget);
]]></source>
<p>
If you want this protocol to represent the default SSL protocol
implementation, simply register
it under 'https' designator, which will make the protocol object take place
of the existing one
</p>
<source><![CDATA[
Protocol.registerProtocol("https",
new Protocol("https", new MySSLSocketFactory(), 443));
HttpClient httpclient = new HttpClient();
GetMethod httpget = new GetMethod("https://www.whatever.com/");
httpclient.executeMethod(httpget);
]]></source>
</li>
</ul>
</section>
<section name="Examples of SSL customization in HttpClient">
<p>
There are several custom socket factories available in our contribution
package. They can
be a good start for those who seek to tailor the behavior of the HTTPS
protocol to the specific
needs of their application:
</p>
<ul>
<li>
<a
href="http://cvs.apache.org/viewcvs/jakarta-commons/httpclient/src/contrib/org/apache/commons/httpclient/contrib/ssl/EasySSLProtocolSocketFactory.java?rev=HEAD">
EasySSLProtocolSocketFactory</a> can be used to create SSL connections
that allow the target
server to authenticate with a self-signed certificate.
</li>
<li>
<a
href="http://cvs.apache.org/viewcvs/jakarta-commons/httpclient/src/contrib/org/apache/commons/httpclient/contrib/ssl/StrictSSLProtocolSocketFactory.java?rev=HEAD">
StrictSSLProtocolSocketFactory</a> can be used to create SSL connections
that can optionally perform host name verification in order to help preventing
man-in-the-middle type of attacks.
</li>
</ul>
</section>
<section name="Known limitations and problems">
<ol>
<li>
<p>
<strong>Persistent SSL connections do not work on Sun's JVMs below
1.4</strong>
</p>
<p>
Due to what appears to be a bug in Sun's older (below 1.4) implementation
of
Java Virtual Machines or JSSE there's no reliable way of telling if an SSL
connection
is 'stale' or not. For example, the HTTP 1.1 specification permits HTTP
servers in
'keep-alive' mode to drop connection to the client after a given period
inactivity
without having to notify the client, effectively rendering such connection
unusable or
'stale'. For the HTTP agent written in Java there's no reliable way known
to us to test
if a connection is 'stale' other than attempting to perform a read on it.
If you happen
to know a better way we would be delighted to hear about it. Rather
unfortunately, a read
operation on an idle SSL connection on Sun JVM older than 1.4 returns 'end
of stream'
instead of an expected read timeout. That effectively makes the connection
appear 'stale'
to the HttpClient, which leaves it with no other way but to drop the
connection and to
open a new one, thus defeating HTTP 1.1 keep-alive mechanism and resulting
in significant
performance degradation (SSL authentication is a highly time consuming
operation). Sun's
Java 1.4 SSL implementation does not exhibit this kind of problem. Plain
sockets on all
JVMs are not subject to the problem either.
</p>
<p>
<strong>Workaround:</strong> If persistent SSL connections support is an
issue for your
application we strongly advise you to upgrade to Java 1.4.
</p>
</li>
<li>
<p>
<strong>Non-preemptive authentication with a HTTPS server fails when
connecting via a proxy</strong>
</p>
<p>
This problem is caused by a serious flaw in HttpClient design and cannot be
fixed without
breaking the existing APIs. The problem will be addressed in HttpClient
release 2.1.
</p>
<p>
<strong>Workaround:</strong> Use preemptive server authentication. Please
note that only
BASIC authentication can be used preemptively. For more detailed
information please refer
to the <a href="authentication.html">Authentication Guide</a>.
</p>
</li>
</ol>
</section>
<section name="Troubleshooting">
<p>
If you are unlucky and HTTPS with HttpClient does not work for you, it may
be a bit premature
to blame it squarely on HttpClient. The JSSE is highly prone to
configuration problems, especially
on older JVMs, which it is not an integral part of.
</p>
<p>
The application below can be used as an ultimate test that can reliably tell
if SSL configured
properly, as it relies on a plain socket in order to communicate with the
target server. If you
get an exception while executing this code, most certainly SSL is not
functioning properly with
your JVM. Please refer to Sun's official resources for support or additional
details on JSSE
configuration.
</p>
<source><![CDATA[
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.Socket;
import javax.net.ssl.SSLSocketFactory;
public class Test {
public static final String TARGET_HTTPS_SERVER = "www.verisign.com";
public static final int TARGET_HTTPS_PORT = 443;
public static void main(String[] args) throws Exception {
Socket socket = SSLSocketFactory.getDefault().
createSocket(TARGET_HTTPS_SERVER, TARGET_HTTPS_PORT);
try {
Writer out = new OutputStreamWriter(
socket.getOutputStream(), "ISO-8859-1");
out.write("GET / HTTP/1.1\r\n");
out.write("Host: " + TARGET_HTTPS_SERVER + ":" +
TARGET_HTTPS_PORT + "\r\n");
out.write("Agent: SSL-TEST\r\n");
out.write("\r\n");
out.flush();
BufferedReader in = new BufferedReader(
new InputStreamReader(socket.getInputStream(), "ISO-8859-1"));
String line = null;
while ((line = in.readLine()) != null) {
System.out.println(line);
}
} finally {
socket.close();
}
}
}
]]></source>
</section>
</body>
</document>
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]