Merged branch 'jetty-9.3.x' into 'jetty-9.4.x'.
This commit is contained in:
commit
5fe1ff697e
|
@ -19,7 +19,6 @@
|
|||
package org.eclipse.jetty.client;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.channels.ClosedChannelException;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
|
@ -109,23 +108,10 @@ public class HostnameVerificationTest
|
|||
}
|
||||
catch (ExecutionException x)
|
||||
{
|
||||
// The test may fail in 2 ways, since the CertificateException thrown because of the hostname
|
||||
// verification failure is not rethrown immediately by the JDK SSL implementation, but only
|
||||
// rethrown on the next read or write.
|
||||
// Therefore this test may catch a SSLHandshakeException, or a ClosedChannelException.
|
||||
// If it is the former, we verify that its cause is a CertificateException.
|
||||
|
||||
// ExecutionException wraps an SSLHandshakeException
|
||||
Throwable cause = x.getCause();
|
||||
if (cause==null)
|
||||
{
|
||||
x.printStackTrace();
|
||||
Assert.fail("No cause?");
|
||||
}
|
||||
if (cause instanceof SSLHandshakeException)
|
||||
Assert.assertThat(cause.getCause().getCause(), Matchers.instanceOf(CertificateException.class));
|
||||
else
|
||||
Assert.assertThat(cause, Matchers.instanceOf(ClosedChannelException.class));
|
||||
Assert.assertThat(cause, Matchers.instanceOf(SSLHandshakeException.class));
|
||||
Throwable root = cause.getCause().getCause();
|
||||
Assert.assertThat(root, Matchers.instanceOf(CertificateException.class));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -134,7 +120,7 @@ public class HostnameVerificationTest
|
|||
* work fine.
|
||||
*
|
||||
* @throws Exception on test failure
|
||||
*
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void simpleGetWithHostnameVerificationDisabledTest() throws Exception
|
||||
|
|
|
@ -26,7 +26,6 @@ import java.io.OutputStream;
|
|||
import java.net.SocketTimeoutException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
|
@ -105,13 +104,10 @@ public class SslBytesClientTest extends SslBytesTest
|
|||
final SSLSocket server = (SSLSocket)acceptor.accept();
|
||||
server.setUseClientMode(false);
|
||||
|
||||
Future<Object> handshake = threadPool.submit(new Callable<Object>()
|
||||
Future<Object> handshake = threadPool.submit(() ->
|
||||
{
|
||||
public Object call() throws Exception
|
||||
{
|
||||
server.startHandshake();
|
||||
return null;
|
||||
}
|
||||
server.startHandshake();
|
||||
return null;
|
||||
});
|
||||
|
||||
// Client Hello
|
||||
|
@ -185,13 +181,10 @@ public class SslBytesClientTest extends SslBytesTest
|
|||
final SSLSocket server = (SSLSocket)acceptor.accept();
|
||||
server.setUseClientMode(false);
|
||||
|
||||
Future<Object> handshake = threadPool.submit(new Callable<Object>()
|
||||
Future<Object> handshake = threadPool.submit(() ->
|
||||
{
|
||||
public Object call() throws Exception
|
||||
{
|
||||
server.startHandshake();
|
||||
return null;
|
||||
}
|
||||
server.startHandshake();
|
||||
return null;
|
||||
});
|
||||
|
||||
SimpleProxy.AutomaticFlow automaticProxyFlow = proxy.startAutomaticFlow();
|
||||
|
@ -222,13 +215,10 @@ public class SslBytesClientTest extends SslBytesTest
|
|||
Assert.assertTrue(automaticProxyFlow.stop(5, TimeUnit.SECONDS));
|
||||
|
||||
// Renegotiate
|
||||
Future<Object> renegotiation = threadPool.submit(new Callable<Object>()
|
||||
Future<Object> renegotiation = threadPool.submit(() ->
|
||||
{
|
||||
public Object call() throws Exception
|
||||
{
|
||||
server.startHandshake();
|
||||
return null;
|
||||
}
|
||||
server.startHandshake();
|
||||
return null;
|
||||
});
|
||||
|
||||
// Renegotiation Handshake
|
||||
|
@ -307,13 +297,10 @@ public class SslBytesClientTest extends SslBytesTest
|
|||
final SSLSocket server = (SSLSocket)acceptor.accept();
|
||||
server.setUseClientMode(false);
|
||||
|
||||
Future<Object> handshake = threadPool.submit(new Callable<Object>()
|
||||
Future<Object> handshake = threadPool.submit(() ->
|
||||
{
|
||||
public Object call() throws Exception
|
||||
{
|
||||
server.startHandshake();
|
||||
return null;
|
||||
}
|
||||
server.startHandshake();
|
||||
return null;
|
||||
});
|
||||
|
||||
SimpleProxy.AutomaticFlow automaticProxyFlow = proxy.startAutomaticFlow();
|
||||
|
@ -344,13 +331,10 @@ public class SslBytesClientTest extends SslBytesTest
|
|||
Assert.assertTrue(automaticProxyFlow.stop(5, TimeUnit.SECONDS));
|
||||
|
||||
// Renegotiate
|
||||
threadPool.submit(new Callable<Object>()
|
||||
threadPool.submit(() ->
|
||||
{
|
||||
public Object call() throws Exception
|
||||
{
|
||||
server.startHandshake();
|
||||
return null;
|
||||
}
|
||||
server.startHandshake();
|
||||
return null;
|
||||
});
|
||||
|
||||
// Renegotiation Handshake
|
||||
|
@ -358,6 +342,9 @@ public class SslBytesClientTest extends SslBytesTest
|
|||
Assert.assertEquals(TLSRecord.Type.HANDSHAKE, record.getType());
|
||||
proxy.flushToClient(record);
|
||||
|
||||
// Client sends close alert.
|
||||
record = proxy.readFromClient();
|
||||
Assert.assertEquals(TLSRecord.Type.ALERT, record.getType());
|
||||
record = proxy.readFromClient();
|
||||
Assert.assertNull(record);
|
||||
|
||||
|
|
|
@ -30,7 +30,6 @@ import java.nio.channels.SelectionKey;
|
|||
import java.nio.channels.SocketChannel;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
@ -242,14 +241,10 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
{
|
||||
final SSLSocket client = newClient();
|
||||
|
||||
Future<Object> handshake = threadPool.submit(new Callable<Object>()
|
||||
Future<Object> handshake = threadPool.submit(() ->
|
||||
{
|
||||
@Override
|
||||
public Object call() throws Exception
|
||||
{
|
||||
client.startHandshake();
|
||||
return null;
|
||||
}
|
||||
client.startHandshake();
|
||||
return null;
|
||||
});
|
||||
|
||||
// Client Hello
|
||||
|
@ -316,14 +311,10 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
|
||||
final SSLSocket client2 = newClient(proxy);
|
||||
|
||||
Future<Object> handshake = threadPool.submit(new Callable<Object>()
|
||||
threadPool.submit(() ->
|
||||
{
|
||||
@Override
|
||||
public Object call() throws Exception
|
||||
{
|
||||
client2.startHandshake();
|
||||
return null;
|
||||
}
|
||||
client2.startHandshake();
|
||||
return null;
|
||||
});
|
||||
|
||||
// Client Hello with SessionID
|
||||
|
@ -366,19 +357,14 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
System.arraycopy(doneBytes, 0, chunk, recordBytes.length, doneBytes.length);
|
||||
System.arraycopy(closeRecordBytes, 0, chunk, recordBytes.length + doneBytes.length, closeRecordBytes.length);
|
||||
proxy.flushToServer(0, chunk);
|
||||
|
||||
// Close the raw socket
|
||||
proxy.flushToServer(null);
|
||||
|
||||
// Expect the server to send a FIN as well
|
||||
// Expect the server to send a TLS Alert.
|
||||
record = proxy.readFromServer();
|
||||
Assert.assertNotNull(record);
|
||||
Assert.assertEquals(TLSRecord.Type.ALERT, record.getType());
|
||||
record = proxy.readFromServer();
|
||||
if (record!=null)
|
||||
{
|
||||
// Close alert snuck out // TODO check if this is acceptable
|
||||
Assert.assertEquals(Type.ALERT,record.getType());
|
||||
record = proxy.readFromServer();
|
||||
}
|
||||
|
||||
Assert.assertNull(record);
|
||||
|
||||
// Check that we did not spin
|
||||
|
@ -393,14 +379,10 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
{
|
||||
final SSLSocket client = newClient();
|
||||
|
||||
Future<Object> handshake = threadPool.submit(new Callable<Object>()
|
||||
Future<Object> handshake = threadPool.submit(() ->
|
||||
{
|
||||
@Override
|
||||
public Object call() throws Exception
|
||||
{
|
||||
client.startHandshake();
|
||||
return null;
|
||||
}
|
||||
client.startHandshake();
|
||||
return null;
|
||||
});
|
||||
|
||||
// Client Hello
|
||||
|
@ -486,7 +468,7 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
if (record!=null)
|
||||
{
|
||||
Assert.assertEquals(record.getType(),Type.ALERT);
|
||||
|
||||
|
||||
// Now should be a raw close
|
||||
record = proxy.readFromServer();
|
||||
Assert.assertNull(String.valueOf(record), record);
|
||||
|
@ -498,14 +480,10 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
{
|
||||
final SSLSocket client = newClient();
|
||||
|
||||
threadPool.submit(new Callable<Object>()
|
||||
threadPool.submit(() ->
|
||||
{
|
||||
@Override
|
||||
public Object call() throws Exception
|
||||
{
|
||||
client.startHandshake();
|
||||
return null;
|
||||
}
|
||||
client.startHandshake();
|
||||
return null;
|
||||
});
|
||||
|
||||
// Client Hello
|
||||
|
@ -531,14 +509,10 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
{
|
||||
final SSLSocket client = newClient();
|
||||
|
||||
threadPool.submit(new Callable<Object>()
|
||||
threadPool.submit(() ->
|
||||
{
|
||||
@Override
|
||||
public Object call() throws Exception
|
||||
{
|
||||
client.startHandshake();
|
||||
return null;
|
||||
}
|
||||
client.startHandshake();
|
||||
return null;
|
||||
});
|
||||
|
||||
// Client Hello
|
||||
|
@ -586,19 +560,15 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
client.startHandshake();
|
||||
Assert.assertTrue(automaticProxyFlow.stop(5, TimeUnit.SECONDS));
|
||||
|
||||
threadPool.submit(new Callable<Object>()
|
||||
threadPool.submit(() ->
|
||||
{
|
||||
@Override
|
||||
public Object call() throws Exception
|
||||
{
|
||||
OutputStream clientOutput = client.getOutputStream();
|
||||
clientOutput.write(("" +
|
||||
"GET / HTTP/1.1\r\n" +
|
||||
"Host: localhost\r\n" +
|
||||
"\r\n").getBytes(StandardCharsets.UTF_8));
|
||||
clientOutput.flush();
|
||||
return null;
|
||||
}
|
||||
OutputStream clientOutput = client.getOutputStream();
|
||||
clientOutput.write(("" +
|
||||
"GET / HTTP/1.1\r\n" +
|
||||
"Host: localhost\r\n" +
|
||||
"\r\n").getBytes(StandardCharsets.UTF_8));
|
||||
clientOutput.flush();
|
||||
return null;
|
||||
});
|
||||
|
||||
// Application data
|
||||
|
@ -628,19 +598,15 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
client.startHandshake();
|
||||
Assert.assertTrue(automaticProxyFlow.stop(5, TimeUnit.SECONDS));
|
||||
|
||||
Future<Object> request = threadPool.submit(new Callable<Object>()
|
||||
Future<Object> request = threadPool.submit(() ->
|
||||
{
|
||||
@Override
|
||||
public Object call() throws Exception
|
||||
{
|
||||
OutputStream clientOutput = client.getOutputStream();
|
||||
clientOutput.write(("" +
|
||||
"GET / HTTP/1.1\r\n" +
|
||||
"Host: localhost\r\n" +
|
||||
"\r\n").getBytes(StandardCharsets.UTF_8));
|
||||
clientOutput.flush();
|
||||
return null;
|
||||
}
|
||||
OutputStream clientOutput = client.getOutputStream();
|
||||
clientOutput.write(("" +
|
||||
"GET / HTTP/1.1\r\n" +
|
||||
"Host: localhost\r\n" +
|
||||
"\r\n").getBytes(StandardCharsets.UTF_8));
|
||||
clientOutput.flush();
|
||||
return null;
|
||||
});
|
||||
|
||||
// Application data
|
||||
|
@ -677,14 +643,10 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
{
|
||||
final SSLSocket client = newClient();
|
||||
|
||||
Future<Object> handshake = threadPool.submit(new Callable<Object>()
|
||||
Future<Object> handshake = threadPool.submit(() ->
|
||||
{
|
||||
@Override
|
||||
public Object call() throws Exception
|
||||
{
|
||||
client.startHandshake();
|
||||
return null;
|
||||
}
|
||||
client.startHandshake();
|
||||
return null;
|
||||
});
|
||||
|
||||
// Client Hello
|
||||
|
@ -721,19 +683,15 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
|
||||
Assert.assertNull(handshake.get(1, TimeUnit.SECONDS));
|
||||
|
||||
Future<Object> request = threadPool.submit(new Callable<Object>()
|
||||
Future<Object> request = threadPool.submit(() ->
|
||||
{
|
||||
@Override
|
||||
public Object call() throws Exception
|
||||
{
|
||||
OutputStream clientOutput = client.getOutputStream();
|
||||
clientOutput.write(("" +
|
||||
"GET / HTTP/1.1\r\n" +
|
||||
"Host: localhost\r\n" +
|
||||
"\r\n").getBytes(StandardCharsets.UTF_8));
|
||||
clientOutput.flush();
|
||||
return null;
|
||||
}
|
||||
OutputStream clientOutput = client.getOutputStream();
|
||||
clientOutput.write(("" +
|
||||
"GET / HTTP/1.1\r\n" +
|
||||
"Host: localhost\r\n" +
|
||||
"\r\n").getBytes(StandardCharsets.UTF_8));
|
||||
clientOutput.flush();
|
||||
return null;
|
||||
});
|
||||
|
||||
// Application data
|
||||
|
@ -782,7 +740,7 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
if (record!=null)
|
||||
{
|
||||
Assert.assertEquals(record.getType(),Type.ALERT);
|
||||
|
||||
|
||||
// Now should be a raw close
|
||||
record = proxy.readFromServer();
|
||||
Assert.assertNull(String.valueOf(record), record);
|
||||
|
@ -801,19 +759,15 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
client.startHandshake();
|
||||
Assert.assertTrue(automaticProxyFlow.stop(5, TimeUnit.SECONDS));
|
||||
|
||||
Future<Object> request = threadPool.submit(new Callable<Object>()
|
||||
Future<Object> request = threadPool.submit(() ->
|
||||
{
|
||||
@Override
|
||||
public Object call() throws Exception
|
||||
{
|
||||
OutputStream clientOutput = client.getOutputStream();
|
||||
clientOutput.write(("" +
|
||||
"GET / HTTP/1.1\r\n" +
|
||||
"Host: localhost\r\n" +
|
||||
"\r\n").getBytes(StandardCharsets.UTF_8));
|
||||
clientOutput.flush();
|
||||
return null;
|
||||
}
|
||||
OutputStream clientOutput = client.getOutputStream();
|
||||
clientOutput.write(("" +
|
||||
"GET / HTTP/1.1\r\n" +
|
||||
"Host: localhost\r\n" +
|
||||
"\r\n").getBytes(StandardCharsets.UTF_8));
|
||||
clientOutput.flush();
|
||||
return null;
|
||||
});
|
||||
|
||||
// Application data
|
||||
|
@ -844,7 +798,7 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
if (record!=null)
|
||||
{
|
||||
Assert.assertEquals(record.getType(),Type.ALERT);
|
||||
|
||||
|
||||
// Now should be a raw close
|
||||
record = proxy.readFromServer();
|
||||
Assert.assertNull(String.valueOf(record), record);
|
||||
|
@ -876,19 +830,15 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
client.startHandshake();
|
||||
Assert.assertTrue(automaticProxyFlow.stop(5, TimeUnit.SECONDS));
|
||||
|
||||
Future<Object> request = threadPool.submit(new Callable<Object>()
|
||||
Future<Object> request = threadPool.submit(() ->
|
||||
{
|
||||
@Override
|
||||
public Object call() throws Exception
|
||||
{
|
||||
OutputStream clientOutput = client.getOutputStream();
|
||||
clientOutput.write(("" +
|
||||
"GET / HTTP/1.1\r\n" +
|
||||
"Host: localhost\r\n" +
|
||||
"\r\n").getBytes(StandardCharsets.UTF_8));
|
||||
clientOutput.flush();
|
||||
return null;
|
||||
}
|
||||
OutputStream clientOutput = client.getOutputStream();
|
||||
clientOutput.write(("" +
|
||||
"GET / HTTP/1.1\r\n" +
|
||||
"Host: localhost\r\n" +
|
||||
"\r\n").getBytes(StandardCharsets.UTF_8));
|
||||
clientOutput.flush();
|
||||
return null;
|
||||
});
|
||||
|
||||
// Application data
|
||||
|
@ -919,7 +869,7 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
if (record!=null)
|
||||
{
|
||||
Assert.assertEquals(record.getType(),Type.ALERT);
|
||||
|
||||
|
||||
// Now should be a raw close
|
||||
record = proxy.readFromServer();
|
||||
Assert.assertNull(String.valueOf(record), record);
|
||||
|
@ -946,19 +896,15 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
client.startHandshake();
|
||||
Assert.assertTrue(automaticProxyFlow.stop(5, TimeUnit.SECONDS));
|
||||
|
||||
Future<Object> request = threadPool.submit(new Callable<Object>()
|
||||
Future<Object> request = threadPool.submit(() ->
|
||||
{
|
||||
@Override
|
||||
public Object call() throws Exception
|
||||
{
|
||||
OutputStream clientOutput = client.getOutputStream();
|
||||
clientOutput.write(("" +
|
||||
"GET / HTTP/1.1\r\n" +
|
||||
"Host: localhost\r\n" +
|
||||
"\r\n").getBytes(StandardCharsets.UTF_8));
|
||||
clientOutput.flush();
|
||||
return null;
|
||||
}
|
||||
OutputStream clientOutput = client.getOutputStream();
|
||||
clientOutput.write(("" +
|
||||
"GET / HTTP/1.1\r\n" +
|
||||
"Host: localhost\r\n" +
|
||||
"\r\n").getBytes(StandardCharsets.UTF_8));
|
||||
clientOutput.flush();
|
||||
return null;
|
||||
});
|
||||
|
||||
// Application data
|
||||
|
@ -981,7 +927,7 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
if (record!=null)
|
||||
{
|
||||
Assert.assertEquals(record.getType(),Type.ALERT);
|
||||
|
||||
|
||||
// Now should be a raw close
|
||||
record = proxy.readFromServer();
|
||||
Assert.assertNull(String.valueOf(record), record);
|
||||
|
@ -1005,19 +951,15 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
client.startHandshake();
|
||||
Assert.assertTrue(automaticProxyFlow.stop(5, TimeUnit.SECONDS));
|
||||
|
||||
Future<Object> request = threadPool.submit(new Callable<Object>()
|
||||
Future<Object> request = threadPool.submit(() ->
|
||||
{
|
||||
@Override
|
||||
public Object call() throws Exception
|
||||
{
|
||||
OutputStream clientOutput = client.getOutputStream();
|
||||
clientOutput.write(("" +
|
||||
"GET / HTTP/1.1\r\n" +
|
||||
"Host: localhost\r\n" +
|
||||
"\r\n").getBytes(StandardCharsets.UTF_8));
|
||||
clientOutput.flush();
|
||||
return null;
|
||||
}
|
||||
OutputStream clientOutput = client.getOutputStream();
|
||||
clientOutput.write(("" +
|
||||
"GET / HTTP/1.1\r\n" +
|
||||
"Host: localhost\r\n" +
|
||||
"\r\n").getBytes(StandardCharsets.UTF_8));
|
||||
clientOutput.flush();
|
||||
return null;
|
||||
});
|
||||
|
||||
// Application data
|
||||
|
@ -1038,7 +980,7 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
if (record!=null)
|
||||
{
|
||||
Assert.assertEquals(record.getType(),Type.ALERT);
|
||||
|
||||
|
||||
// Now should be a raw close
|
||||
record = proxy.readFromServer();
|
||||
Assert.assertNull(String.valueOf(record), record);
|
||||
|
@ -1058,7 +1000,7 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
{
|
||||
// Don't run on Windows (buggy JVM)
|
||||
Assume.assumeTrue(!OS.IS_WINDOWS);
|
||||
|
||||
|
||||
final SSLSocket client = newClient();
|
||||
|
||||
SimpleProxy.AutomaticFlow automaticProxyFlow = proxy.startAutomaticFlow();
|
||||
|
@ -1068,21 +1010,17 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
byte[] data = new byte[128 * 1024];
|
||||
Arrays.fill(data, (byte)'X');
|
||||
final String content = new String(data, StandardCharsets.UTF_8);
|
||||
Future<Object> request = threadPool.submit(new Callable<Object>()
|
||||
Future<Object> request = threadPool.submit(() ->
|
||||
{
|
||||
@Override
|
||||
public Object call() throws Exception
|
||||
{
|
||||
OutputStream clientOutput = client.getOutputStream();
|
||||
clientOutput.write(("" +
|
||||
"GET /echo HTTP/1.1\r\n" +
|
||||
"Host: localhost\r\n" +
|
||||
"Content-Length: " + content.length() + "\r\n" +
|
||||
"\r\n" +
|
||||
content).getBytes(StandardCharsets.UTF_8));
|
||||
clientOutput.flush();
|
||||
return null;
|
||||
}
|
||||
OutputStream clientOutput = client.getOutputStream();
|
||||
clientOutput.write(("" +
|
||||
"GET /echo HTTP/1.1\r\n" +
|
||||
"Host: localhost\r\n" +
|
||||
"Content-Length: " + content.length() + "\r\n" +
|
||||
"\r\n" +
|
||||
content).getBytes(StandardCharsets.UTF_8));
|
||||
clientOutput.flush();
|
||||
return null;
|
||||
});
|
||||
|
||||
// Nine TLSRecords will be generated for the request
|
||||
|
@ -1119,7 +1057,7 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
{
|
||||
// Don't run on Windows (buggy JVM)
|
||||
Assume.assumeTrue(!OS.IS_WINDOWS);
|
||||
|
||||
|
||||
final SSLSocket client = newClient();
|
||||
|
||||
SimpleProxy.AutomaticFlow automaticProxyFlow = proxy.startAutomaticFlow();
|
||||
|
@ -1129,21 +1067,17 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
byte[] data = new byte[128 * 1024];
|
||||
Arrays.fill(data, (byte)'X');
|
||||
final String content = new String(data, StandardCharsets.UTF_8);
|
||||
Future<Object> request = threadPool.submit(new Callable<Object>()
|
||||
Future<Object> request = threadPool.submit(() ->
|
||||
{
|
||||
@Override
|
||||
public Object call() throws Exception
|
||||
{
|
||||
OutputStream clientOutput = client.getOutputStream();
|
||||
clientOutput.write(("" +
|
||||
"GET /echo_suppress_exception HTTP/1.1\r\n" +
|
||||
"Host: localhost\r\n" +
|
||||
"Content-Length: " + content.length() + "\r\n" +
|
||||
"\r\n" +
|
||||
content).getBytes(StandardCharsets.UTF_8));
|
||||
clientOutput.flush();
|
||||
return null;
|
||||
}
|
||||
OutputStream clientOutput = client.getOutputStream();
|
||||
clientOutput.write(("" +
|
||||
"GET /echo_suppress_exception HTTP/1.1\r\n" +
|
||||
"Host: localhost\r\n" +
|
||||
"Content-Length: " + content.length() + "\r\n" +
|
||||
"\r\n" +
|
||||
content).getBytes(StandardCharsets.UTF_8));
|
||||
clientOutput.flush();
|
||||
return null;
|
||||
});
|
||||
|
||||
// Nine TLSRecords will be generated for the request,
|
||||
|
@ -1193,19 +1127,15 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
client.startHandshake();
|
||||
Assert.assertTrue(automaticProxyFlow.stop(5, TimeUnit.SECONDS));
|
||||
|
||||
Future<Object> request = threadPool.submit(new Callable<Object>()
|
||||
Future<Object> request = threadPool.submit(() ->
|
||||
{
|
||||
@Override
|
||||
public Object call() throws Exception
|
||||
{
|
||||
OutputStream clientOutput = client.getOutputStream();
|
||||
clientOutput.write(("" +
|
||||
"GET / HTTP/1.1\r\n" +
|
||||
"Host: localhost\r\n" +
|
||||
"\r\n").getBytes(StandardCharsets.UTF_8));
|
||||
clientOutput.flush();
|
||||
return null;
|
||||
}
|
||||
OutputStream clientOutput = client.getOutputStream();
|
||||
clientOutput.write(("" +
|
||||
"GET / HTTP/1.1\r\n" +
|
||||
"Host: localhost\r\n" +
|
||||
"\r\n").getBytes(StandardCharsets.UTF_8));
|
||||
clientOutput.flush();
|
||||
return null;
|
||||
});
|
||||
|
||||
// Application data
|
||||
|
@ -1245,7 +1175,7 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
if (record!=null)
|
||||
{
|
||||
Assert.assertEquals(record.getType(),Type.ALERT);
|
||||
|
||||
|
||||
// Now should be a raw close
|
||||
record = proxy.readFromServer();
|
||||
Assert.assertNull(String.valueOf(record), record);
|
||||
|
@ -1269,22 +1199,18 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
|
||||
final String content = "0123456789ABCDEF";
|
||||
|
||||
Future<Object> request = threadPool.submit(new Callable<Object>()
|
||||
Future<Object> request = threadPool.submit(() ->
|
||||
{
|
||||
@Override
|
||||
public Object call() throws Exception
|
||||
{
|
||||
OutputStream clientOutput = client.getOutputStream();
|
||||
clientOutput.write(("" +
|
||||
"POST / HTTP/1.1\r\n" +
|
||||
"Host: localhost\r\n" +
|
||||
"Content-Type: text/plain\r\n" +
|
||||
"Content-Length: " + content.length() + "\r\n" +
|
||||
"\r\n" +
|
||||
content).getBytes(StandardCharsets.UTF_8));
|
||||
clientOutput.flush();
|
||||
return null;
|
||||
}
|
||||
OutputStream clientOutput = client.getOutputStream();
|
||||
clientOutput.write(("" +
|
||||
"POST / HTTP/1.1\r\n" +
|
||||
"Host: localhost\r\n" +
|
||||
"Content-Type: text/plain\r\n" +
|
||||
"Content-Length: " + content.length() + "\r\n" +
|
||||
"\r\n" +
|
||||
content).getBytes(StandardCharsets.UTF_8));
|
||||
clientOutput.flush();
|
||||
return null;
|
||||
});
|
||||
|
||||
// Application data
|
||||
|
@ -1335,22 +1261,18 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
Arrays.fill(data, (byte)'X');
|
||||
final String content = new String(data, StandardCharsets.UTF_8);
|
||||
|
||||
Future<Object> request = threadPool.submit(new Callable<Object>()
|
||||
Future<Object> request = threadPool.submit(() ->
|
||||
{
|
||||
@Override
|
||||
public Object call() throws Exception
|
||||
{
|
||||
OutputStream clientOutput = client.getOutputStream();
|
||||
clientOutput.write(("" +
|
||||
"POST / HTTP/1.1\r\n" +
|
||||
"Host: localhost\r\n" +
|
||||
"Content-Type: text/plain\r\n" +
|
||||
"Content-Length: " + content.length() + "\r\n" +
|
||||
"\r\n" +
|
||||
content).getBytes(StandardCharsets.UTF_8));
|
||||
clientOutput.flush();
|
||||
return null;
|
||||
}
|
||||
OutputStream clientOutput = client.getOutputStream();
|
||||
clientOutput.write(("" +
|
||||
"POST / HTTP/1.1\r\n" +
|
||||
"Host: localhost\r\n" +
|
||||
"Content-Type: text/plain\r\n" +
|
||||
"Content-Length: " + content.length() + "\r\n" +
|
||||
"\r\n" +
|
||||
content).getBytes(StandardCharsets.UTF_8));
|
||||
clientOutput.flush();
|
||||
return null;
|
||||
});
|
||||
|
||||
// Nine TLSRecords will be generated for the request
|
||||
|
@ -1434,14 +1356,10 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
Assert.assertTrue(automaticProxyFlow.stop(5, TimeUnit.SECONDS));
|
||||
|
||||
// Renegotiate
|
||||
threadPool.submit(new Callable<Object>()
|
||||
threadPool.submit(() ->
|
||||
{
|
||||
@Override
|
||||
public Object call() throws Exception
|
||||
{
|
||||
client.startHandshake();
|
||||
return null;
|
||||
}
|
||||
client.startHandshake();
|
||||
return null;
|
||||
});
|
||||
|
||||
// Renegotiation Handshake
|
||||
|
@ -1458,15 +1376,11 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
Assert.assertNull(record);
|
||||
|
||||
// Write the rest of the request
|
||||
threadPool.submit(new Callable<Object>()
|
||||
threadPool.submit(() ->
|
||||
{
|
||||
@Override
|
||||
public Object call() throws Exception
|
||||
{
|
||||
clientOutput.write(content2.getBytes(StandardCharsets.UTF_8));
|
||||
clientOutput.flush();
|
||||
return null;
|
||||
}
|
||||
clientOutput.write(content2.getBytes(StandardCharsets.UTF_8));
|
||||
clientOutput.flush();
|
||||
return null;
|
||||
});
|
||||
|
||||
// Trying to write more application data results in an exception since the server closed
|
||||
|
@ -1481,6 +1395,7 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
}
|
||||
catch (IOException expected)
|
||||
{
|
||||
// Expected
|
||||
}
|
||||
|
||||
// Check that we did not spin
|
||||
|
@ -1525,14 +1440,10 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
Assert.assertTrue(automaticProxyFlow.stop(5, TimeUnit.SECONDS));
|
||||
|
||||
// Renegotiate
|
||||
Future<Object> renegotiation = threadPool.submit(new Callable<Object>()
|
||||
Future<Object> renegotiation = threadPool.submit(() ->
|
||||
{
|
||||
@Override
|
||||
public Object call() throws Exception
|
||||
{
|
||||
client.startHandshake();
|
||||
return null;
|
||||
}
|
||||
client.startHandshake();
|
||||
return null;
|
||||
});
|
||||
|
||||
// Renegotiation Handshake
|
||||
|
@ -1580,15 +1491,11 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
Assert.assertNull(renegotiation.get(5, TimeUnit.SECONDS));
|
||||
|
||||
// Write the rest of the request
|
||||
Future<Object> request = threadPool.submit(new Callable<Object>()
|
||||
Future<Object> request = threadPool.submit(() ->
|
||||
{
|
||||
@Override
|
||||
public Object call() throws Exception
|
||||
{
|
||||
clientOutput.write(content2.getBytes(StandardCharsets.UTF_8));
|
||||
clientOutput.flush();
|
||||
return null;
|
||||
}
|
||||
clientOutput.write(content2.getBytes(StandardCharsets.UTF_8));
|
||||
clientOutput.flush();
|
||||
return null;
|
||||
});
|
||||
|
||||
// Three TLSRecords will be generated for the remainder of the content
|
||||
|
@ -1659,14 +1566,10 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
Assert.assertTrue(automaticProxyFlow.stop(5, TimeUnit.SECONDS));
|
||||
|
||||
// Renegotiate
|
||||
Future<Object> renegotiation = threadPool.submit(new Callable<Object>()
|
||||
Future<Object> renegotiation = threadPool.submit(() ->
|
||||
{
|
||||
@Override
|
||||
public Object call() throws Exception
|
||||
{
|
||||
client.startHandshake();
|
||||
return null;
|
||||
}
|
||||
client.startHandshake();
|
||||
return null;
|
||||
});
|
||||
|
||||
// Renegotiation Handshake
|
||||
|
@ -1732,15 +1635,11 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
Assert.assertNull(renegotiation.get(5, TimeUnit.SECONDS));
|
||||
|
||||
// Write the rest of the request
|
||||
Future<Object> request = threadPool.submit(new Callable<Object>()
|
||||
Future<Object> request = threadPool.submit(() ->
|
||||
{
|
||||
@Override
|
||||
public Object call() throws Exception
|
||||
{
|
||||
clientOutput.write(content2.getBytes(StandardCharsets.UTF_8));
|
||||
clientOutput.flush();
|
||||
return null;
|
||||
}
|
||||
clientOutput.write(content2.getBytes(StandardCharsets.UTF_8));
|
||||
clientOutput.flush();
|
||||
return null;
|
||||
});
|
||||
|
||||
// Three TLSRecords will be generated for the remainder of the content
|
||||
|
@ -1847,25 +1746,21 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
{
|
||||
final SSLSocket client = newClient();
|
||||
|
||||
threadPool.submit(new Callable<Object>()
|
||||
threadPool.submit(() ->
|
||||
{
|
||||
@Override
|
||||
public Object call() throws Exception
|
||||
{
|
||||
client.startHandshake();
|
||||
return null;
|
||||
}
|
||||
client.startHandshake();
|
||||
return null;
|
||||
});
|
||||
|
||||
// Instead of passing the Client Hello, we simulate plain text was passed in
|
||||
proxy.flushToServer(0, "GET / HTTP/1.1\r\n".getBytes(StandardCharsets.UTF_8));
|
||||
|
||||
// We expect that the server sends an alert message and closes.
|
||||
// We expect that the server sends the TLS Alert.
|
||||
TLSRecord record = proxy.readFromServer();
|
||||
Assert.assertNotNull(record);
|
||||
Assert.assertEquals(TLSRecord.Type.ALERT, record.getType());
|
||||
record = proxy.readFromServer();
|
||||
Assert.assertNull(String.valueOf(record), record);
|
||||
Assert.assertNull(record);
|
||||
|
||||
// Check that we did not spin
|
||||
TimeUnit.MILLISECONDS.sleep(500);
|
||||
|
@ -1883,27 +1778,24 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
final OutputStream clientOutput = client.getOutputStream();
|
||||
final CountDownLatch latch = new CountDownLatch(1);
|
||||
|
||||
idleHook = new Runnable()
|
||||
idleHook = () ->
|
||||
{
|
||||
public void run()
|
||||
if (latch.getCount()==0)
|
||||
return;
|
||||
try
|
||||
{
|
||||
if (latch.getCount()==0)
|
||||
return;
|
||||
try
|
||||
{
|
||||
// Send request
|
||||
clientOutput.write(("" +
|
||||
"GET / HTTP/1.1\r\n" +
|
||||
"Host: localhost\r\n" +
|
||||
"\r\n").getBytes(StandardCharsets.UTF_8));
|
||||
clientOutput.flush();
|
||||
latch.countDown();
|
||||
}
|
||||
catch (Exception x)
|
||||
{
|
||||
// Latch won't trigger and test will fail
|
||||
x.printStackTrace();
|
||||
}
|
||||
// Send request
|
||||
clientOutput.write(("" +
|
||||
"GET / HTTP/1.1\r\n" +
|
||||
"Host: localhost\r\n" +
|
||||
"\r\n").getBytes(StandardCharsets.UTF_8));
|
||||
clientOutput.flush();
|
||||
latch.countDown();
|
||||
}
|
||||
catch (Exception x)
|
||||
{
|
||||
// Latch won't trigger and test will fail
|
||||
x.printStackTrace();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1983,6 +1875,6 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
Assert.assertEquals(record.getType(),Type.ALERT);
|
||||
record = proxy.readFromServer();
|
||||
}
|
||||
Assert.assertThat(record, Matchers.nullValue());
|
||||
Assert.assertNull(record);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,18 +17,14 @@
|
|||
[[jetty-connectors]]
|
||||
=== Connector Configuration Overview
|
||||
|
||||
Connectors are the mechanism through which Jetty accepts network
|
||||
connections for various protocols. Configuring a connector is a
|
||||
combination of configuring the following:
|
||||
Connectors are the mechanism through which Jetty accepts network connections for various protocols.
|
||||
Configuring a connector is a combination of configuring the following:
|
||||
|
||||
* Network parameters on the connector itself (for example: the listening
|
||||
port).
|
||||
* Network parameters on the connector itself (for example: the listening port).
|
||||
* Services the connector uses (for example: executors, schedulers).
|
||||
* Connection factories that instantiate and configure the protocol for
|
||||
an accepted connection.
|
||||
* Connection factories that instantiate and configure the protocol for an accepted connection.
|
||||
|
||||
Jetty primarily uses a single connector type called
|
||||
link:{JDURL}/org/eclipse/jetty/server/ServerConnector.html[ServerConnector].
|
||||
Jetty primarily uses a single connector type called link:{JDURL}/org/eclipse/jetty/server/ServerConnector.html[ServerConnector].
|
||||
|
||||
____
|
||||
[NOTE]
|
||||
|
@ -36,65 +32,27 @@ Prior to Jetty 9, the type of the connector specified both the protocol and the
|
|||
Jetty 9 has only a selector-based non blocking I/O connector, and a collection of link:{JDURL}/org/eclipse/jetty/server/ConnectionFactory.html[`ConnectionFactories`] now configure the protocol on the connector.
|
||||
____
|
||||
|
||||
The standard Jetty distribution comes with the following Jetty XML files
|
||||
that create and configure connectors; you should examine them as you
|
||||
read this section:
|
||||
The standard Jetty distribution comes with the following Jetty XML files that create and configure connectors; you should examine them as you read this section:
|
||||
|
||||
link:{SRCDIR}/jetty-server/src/main/config/etc/jetty-http.xml[`jetty-http.xml`]::
|
||||
Instantiates a
|
||||
link:{JDURL}/org/eclipse/jetty/server/ServerConnector.html[`ServerConnector`]
|
||||
that accepts HTTP connections (that may be upgraded to WebSocket
|
||||
connections).
|
||||
Instantiates a link:{JDURL}/org/eclipse/jetty/server/ServerConnector.html[`ServerConnector`] that accepts HTTP connections (that may be upgraded to WebSocket connections).
|
||||
link:{SRCDIR}/jetty-server/src/main/config/etc/jetty-ssl.xml[`jetty-ssl.xml`]::
|
||||
Instantiates a
|
||||
link:{JDURL}/org/eclipse/jetty/server/ServerConnector.html[`ServerConnector`]
|
||||
that accepts SSL/TLS connections. On it's own, this connector is not
|
||||
functional and requires one or more of the following files to also be
|
||||
configured to add
|
||||
link:{JDURL}/org/eclipse/jetty/server/ConnectionFactory.html[`ConnectionFactories`]
|
||||
to make the connector functional.
|
||||
Instantiates a link:{JDURL}/org/eclipse/jetty/server/ServerConnector.html[`ServerConnector`] that accepts SSL/TLS connections.
|
||||
On it's own, this connector is not functional and requires one or more of the following files to also be configured to add link:{JDURL}/org/eclipse/jetty/server/ConnectionFactory.html[`ConnectionFactories`] to make the connector functional.
|
||||
link:{SRCDIR}/jetty-server/src/main/config/etc/jetty-https.xml[`jetty-https.xml`]::
|
||||
Adds a
|
||||
link:{JDURL}/org/eclipse/jetty/server/HttpConnectionFactory.html[`HttpConnectionFactory`]
|
||||
to the
|
||||
link:{JDURL}/org/eclipse/jetty/server/ServerConnector.html[`ServerConnector`]
|
||||
configured by `jetty-ssl.xml` which combine to provide support for
|
||||
HTTPS.
|
||||
Adds a link:{JDURL}/org/eclipse/jetty/server/HttpConnectionFactory.html[`HttpConnectionFactory`] to the link:{JDURL}/org/eclipse/jetty/server/ServerConnector.html[`ServerConnector`] configured by `jetty-ssl.xml` which combine to provide support for HTTPS.
|
||||
link:{SRCDIR}/jetty-http2/http2-server/src/main/config/etc/jetty-http2.xml[`jetty-http2.xml`]::
|
||||
Adds a
|
||||
link:{JDURL}/org/eclipse/jetty/http2/server/HTTP2ServerConnectionFactory.html[`Http2ServerConnectionFactory`]
|
||||
to the
|
||||
link:{JDURL}/org/eclipse/jetty/server/ServerConnector.html[`ServerConnector`]
|
||||
configured by `jetty-ssl.xml to support the http2
|
||||
protocol.` Also prepends either `protonego-alpn.xml` or
|
||||
`protonego-npn.xml` so that the next protocol can be negotiated, which
|
||||
allows the same SSL port to handle multiple protocols.
|
||||
Adds a link:{JDURL}/org/eclipse/jetty/http2/server/HTTP2ServerConnectionFactory.html[`Http2ServerConnectionFactory`] to the link:{JDURL}/org/eclipse/jetty/server/ServerConnector.html[`ServerConnector`] configured by `jetty-ssl.xml` to support the http2 protocol. Also prepends either `protonego-alpn.xml` or `protonego-npn.xml` so that the next protocol can be negotiated, which allows the same SSL port to handle multiple protocols.
|
||||
link:{SRCDIR}/jetty-alpn/jetty-alpn-server/src/main/config/etc/jetty-alpn.xml[`jetty-alpn.xml`]::
|
||||
Adds an
|
||||
link:{JDURL}/org/eclipse/jetty/alpn/server/ALPNServerConnectionFactory.html[`ALPNServerConnectionFactory`]
|
||||
to the
|
||||
link:{JDURL}/org/eclipse/jetty/server/ServerConnector.html[`ServerConnector`]
|
||||
configured by `jetty-ssl.xml` which allows the one SSL connector to
|
||||
support multiple protocols with the ALPN extension used to select the
|
||||
protocol to be used for each connection.
|
||||
Adds an link:{JDURL}/org/eclipse/jetty/alpn/server/ALPNServerConnectionFactory.html[`ALPNServerConnectionFactory`] to the link:{JDURL}/org/eclipse/jetty/server/ServerConnector.html[`ServerConnector`] configured by `jetty-ssl.xml` which allows the one SSL connector to support multiple protocols with the ALPN extension used to select the protocol to be used for each connection.
|
||||
|
||||
Typically you need to configure very little on connectors other than set
|
||||
the listening port (see link:#jetty-connectors-network-settings[Network
|
||||
Settings]), and perhaps enable `X-Forwarded-For` customization (see
|
||||
link:#jetty-connectors-http-configuration[HTTP Configuration]). Most
|
||||
other settings are for expert configuration only.
|
||||
Typically you need to configure very little on connectors other than set the listening port (see link:#jetty-connectors-network-settings[Network Settings]), and perhaps enable `X-Forwarded-For` customization (see link:#jetty-connectors-http-configuration[HTTP Configuration]).
|
||||
Most other settings are for expert configuration only.
|
||||
|
||||
==== Constructing a `ServerConnector`
|
||||
|
||||
The services a
|
||||
link:{JDURL}/org/eclipse/jetty/server/ServerConnector.html[`ServerConnector`]
|
||||
instance uses are set by constructor injection and once instantiated
|
||||
cannot be changed. Most of the services may be defaulted with null or 0
|
||||
values so that a reasonable default is used, thus for most purposes only
|
||||
the Server and the connection factories need to be passed to the
|
||||
connector constructor. In Jetty XML (that is, in
|
||||
link:{SRCDIR}/jetty-server/src/main/config/etc/jetty-http.xml[`jetty-http.xml`]),
|
||||
you can do this with:
|
||||
The services a link:{JDURL}/org/eclipse/jetty/server/ServerConnector.html[`ServerConnector`] instance uses are set by constructor injection and once instantiated cannot be changed.
|
||||
Most of the services may be defaulted with null or 0 values so that a reasonable default is used, thus for most purposes only the Server and the connection factories need to be passed to the connector constructor. In Jetty XML (that is, in link:{SRCDIR}/jetty-server/src/main/config/etc/jetty-http.xml[`jetty-http.xml`]), you can do this by:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
|
@ -109,17 +67,14 @@ you can do this with:
|
|||
</New>
|
||||
----
|
||||
|
||||
You can see the other arguments that can be passed when constructing a
|
||||
`ServerConnector` in the
|
||||
link:{JDURL}/org/eclipse/jetty/server/ServerConnector.html#ServerConnector%28org.eclipse.jetty.server.Server,%20java.util.concurrent.Executor,%20org.eclipse.jetty.util.thread.Scheduler,%20org.eclipse.jetty.io.ByteBufferPool,%20int,%20int,%20org.eclipse.jetty.server.ConnectionFactory...%29[Javadoc].
|
||||
You can see the other arguments that can be passed when constructing a `ServerConnector` in the link:{JDURL}/org/eclipse/jetty/server/ServerConnector.html#ServerConnector%28org.eclipse.jetty.server.Server,%20java.util.concurrent.Executor,%20org.eclipse.jetty.util.thread.Scheduler,%20org.eclipse.jetty.io.ByteBufferPool,%20int,%20int,%20org.eclipse.jetty.server.ConnectionFactory...%29[Javadoc].
|
||||
Typically the defaults are sufficient for almost all deployments.
|
||||
|
||||
[[jetty-connectors-network-settings]]
|
||||
==== Network Settings.
|
||||
|
||||
You configure connector network settings by calling setters on the
|
||||
connector before it is started. For example, you can set the port with
|
||||
the Jetty XML:
|
||||
You configure connector network settings by calling setters on the connector before it is started.
|
||||
For example, you can set the port with the Jetty XML:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
|
@ -131,10 +86,8 @@ the Jetty XML:
|
|||
</New>
|
||||
----
|
||||
|
||||
Values in Jetty XML can also be parameterized so that they may be passed
|
||||
from property files or set on the command line. Thus typically the port
|
||||
is set within Jetty XML, but uses the `Property` element to be
|
||||
customizable:
|
||||
Values in Jetty XML can also be parameterized so that they may be passed from property files or set on the command line.
|
||||
Thus typically the port is set within Jetty XML, but uses the `Property` element to be customizable:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
|
@ -146,70 +99,43 @@ customizable:
|
|||
</New>
|
||||
----
|
||||
|
||||
The network settings that you can set on the
|
||||
link:{JDURL}/org/eclipse/jetty/server/ServerConnector.html[`ServerConnector`]
|
||||
include:
|
||||
The network settings that you can set on the link:{JDURL}/org/eclipse/jetty/server/ServerConnector.html[`ServerConnector`] include:
|
||||
|
||||
.Connector Configuration
|
||||
[width="100%",cols="22%,78%",options="header",]
|
||||
|=======================================================================
|
||||
|Field |Description
|
||||
|host |The network interface this connector binds to as an IP address or
|
||||
a hostname. If null or 0.0.0.0, bind to all interfaces.
|
||||
|host |The network interface this connector binds to as an IP address or a hostname.
|
||||
If null or 0.0.0.0, bind to all interfaces.
|
||||
|
||||
|port |The configured port for the connector or 0 a random available
|
||||
port may be used (selected port available via `getLocalPort()`).
|
||||
|port |The configured port for the connector or 0 a random available port may be used (selected port available via `getLocalPort()`).
|
||||
|
||||
|idleTimeout |The time in milliseconds that the connection can be idle
|
||||
before it is closed.
|
||||
|idleTimeout |The time in milliseconds that the connection can be idle before it is closed.
|
||||
|
||||
|defaultProtocol |The name of the default protocol used to select a
|
||||
`ConnectionFactory` instance. This defaults to the first
|
||||
`ConnectionFactory` added to the connector.
|
||||
|defaultProtocol |The name of the default protocol used to select a `ConnectionFactory` instance. This defaults to the first `ConnectionFactory` added to the connector.
|
||||
|
||||
|stopTimeout |The time in milliseconds to wait before gently stopping a
|
||||
connector.
|
||||
|stopTimeout |The time in milliseconds to wait before gently stopping a connector.
|
||||
|
||||
|acceptQueueSize |The size of the pending connection backlog. The exact
|
||||
interpretation is JVM and operating system specific and you can ignore
|
||||
it. Higher values allow more connections to wait pending an acceptor
|
||||
thread. Because the exact interpretation is deployment dependent, it is
|
||||
best to keep this value as the default unless there is a specific
|
||||
connection issue for a specific OS that you need to address.
|
||||
|acceptQueueSize |The size of the pending connection backlog.
|
||||
The exact interpretation is JVM and operating system specific and you can ignore it.
|
||||
Higher values allow more connections to wait pending an acceptor thread.
|
||||
Because the exact interpretation is deployment dependent, it is best to keep this value as the default unless there is a specific connection issue for a specific OS that you need to address.
|
||||
|
||||
|reuseAddress |Allow the server socket to be rebound even if in
|
||||
http://www.ssfnet.org/Exchange/tcp/tcpTutorialNotes.html[TIME_WAIT]. For
|
||||
servers it is typically OK to leave this as the default true.
|
||||
|reuseAddress |Allow the server socket to be rebound even if in http://www.ssfnet.org/Exchange/tcp/tcpTutorialNotes.html[TIME_WAIT].
|
||||
For servers it is typically OK to leave this as the default true.
|
||||
|
||||
|soLingerTime |A value >=0 set the socket
|
||||
http://stackoverflow.com/questions/3757289/tcp-option-so-linger-zero-when-its-required[SO_LINGER]
|
||||
value in milliseconds. Jetty attempts to gently close all TCP/IP
|
||||
connections with proper half close semantics, so a linger timeout should
|
||||
not be required and thus the default is -1.
|
||||
|soLingerTime |A value greater than zero sets the socket http://stackoverflow.com/questions/3757289/tcp-option-so-linger-zero-when-its-required[SO_LINGER] value in milliseconds.
|
||||
Jetty attempts to gently close all TCP/IP connections with proper half close semantics, so a linger timeout should not be required and thus the default is -1.
|
||||
|=======================================================================
|
||||
|
||||
[[jetty-connectors-http-configuration]]
|
||||
==== HTTP Configuration
|
||||
|
||||
The
|
||||
link:{JDURL}/org/eclipse/jetty/server/HttpConfiguration.html[HttpConfiguration]
|
||||
class holds the configuration for
|
||||
link:{JDURL}/org/eclipse/jetty/server/HttpChannel.html[`HTTPChannel`]s,
|
||||
which you can create 1:1 with each HTTP connection or 1:n on a
|
||||
multiplexed HTTP/2 connection. Thus a `HTTPConfiguration` object is
|
||||
injected into both the HTTP and HTTP/2 connection factories. To avoid
|
||||
duplicate configuration, the standard Jetty distribution creates the
|
||||
common `HttpConfiguration` instance in
|
||||
link:{SRCDIR}/jetty-server/src/main/config/etc/jetty.xml[`jetty.xml`],
|
||||
which is a `Ref` element then used in
|
||||
link:{SRCDIR}/jetty-server/src/main/config/etc/jetty-http.xml[`jetty-http.xml`],
|
||||
link:{SRCDIR}/jetty-server/src/main/config/etc/jetty-https.xml[`jetty-https.xml`]
|
||||
and in
|
||||
link:{SRCDIR}/jetty-http2/http2-server/src/main/config/etc/jetty-http2.xml[`jetty-http2.xml`]
|
||||
The link:{JDURL}/org/eclipse/jetty/server/HttpConfiguration.html[HttpConfiguration] class holds the configuration for link:{JDURL}/org/eclipse/jetty/server/HttpChannel.html[`HTTPChannel`]s, which you can create 1:1 with each HTTP connection or 1:n on a multiplexed HTTP/2 connection.
|
||||
Thus a `HTTPConfiguration` object is injected into both the HTTP and HTTP/2 connection factories.
|
||||
To avoid duplicate configuration, the standard Jetty distribution creates the common `HttpConfiguration` instance in link:{SRCDIR}/jetty-server/src/main/config/etc/jetty.xml[`jetty.xml`], which is a `Ref` element then used in link:{SRCDIR}/jetty-server/src/main/config/etc/jetty-http.xml[`jetty-http.xml`], link:{SRCDIR}/jetty-server/src/main/config/etc/jetty-https.xml[`jetty-https.xml`] and in link:{SRCDIR}/jetty-http2/http2-server/src/main/config/etc/jetty-http2.xml[`jetty-http2.xml`].
|
||||
|
||||
A typical configuration of
|
||||
link:{JDURL}/org/eclipse/jetty/server/HttpConfiguration.html[HttpConfiguration]
|
||||
is:
|
||||
A typical configuration of link:{JDURL}/org/eclipse/jetty/server/HttpConfiguration.html[HttpConfiguration] is:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
|
@ -222,8 +148,7 @@ is:
|
|||
</New>
|
||||
----
|
||||
|
||||
This example HttpConfiguration may be used by reference to the ID
|
||||
"httpConfig":
|
||||
This example HttpConfiguration may be used by reference to the ID "`httpConfig`":
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
|
@ -246,9 +171,7 @@ This example HttpConfiguration may be used by reference to the ID
|
|||
</Call>
|
||||
----
|
||||
|
||||
For SSL based connectors (in `jetty-https.xml` and `jetty-http2.xml`),
|
||||
the common "httpConfig" instance is used as the basis to create an SSL
|
||||
specific configuration with ID "sslHttpConfig":
|
||||
For SSL based connectors (in `jetty-https.xml` and `jetty-http2.xml`), the common "`httpConfig`" instance is used as the basis to create an SSL specific configuration with ID "`sslHttpConfig`":
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
|
@ -260,38 +183,22 @@ specific configuration with ID "sslHttpConfig":
|
|||
</New>
|
||||
----
|
||||
|
||||
This adds a `SecureRequestCustomizer` which adds SSL Session IDs and
|
||||
certificate information as request attributes.
|
||||
This adds a `SecureRequestCustomizer` which adds SSL Session IDs and certificate information as request attributes.
|
||||
|
||||
==== SSL Context Configuration
|
||||
|
||||
The SSL/TLS connectors for HTTPS and HTTP/2 require a certificate to
|
||||
establish a secure connection. Jetty holds certificates in standard JVM
|
||||
keystores and are configured as keystore and truststores on a
|
||||
link:{JDURL}/org/eclipse/jetty/util/ssl/SslContextFactory.html[`SslContextFactory`]
|
||||
instance that is injected into an
|
||||
link:{JDURL}/org/eclipse/jetty/server/SslConnectionFactory.html[`SslConnectionFactory`]
|
||||
instance. An example using the keystore distributed with Jetty
|
||||
(containing a self signed test certificate) is in
|
||||
link:{SRCDIR}/jetty-server/src/main/config/etc/jetty-https.xml[`jetty-https.xml`].
|
||||
The SSL/TLS connectors for HTTPS and HTTP/2 require a certificate to establish a secure connection.
|
||||
Jetty holds certificates in standard JVM keystores and are configured as keystore and truststores on a link:{JDURL}/org/eclipse/jetty/util/ssl/SslContextFactory.html[`SslContextFactory`] instance that is injected into an link:{JDURL}/org/eclipse/jetty/server/SslConnectionFactory.html[`SslConnectionFactory`] instance.
|
||||
An example using the keystore distributed with Jetty (containing a self signed test certificate) is in link:{SRCDIR}/jetty-server/src/main/config/etc/jetty-https.xml[`jetty-https.xml`].
|
||||
Read more about SSL keystores in link:#configuring-ssl[Configuring SSL].
|
||||
|
||||
==== Proxy / Load Balancer Connection Configuration
|
||||
|
||||
Often a Connector needs to be configured to accept connections from an
|
||||
intermediary such as a Reverse Proxy and/or Load Balancer deployed in
|
||||
front of the server. In such environments, the TCP/IP connection
|
||||
terminating on the server does not originate from the client, but from
|
||||
the intermediary, so that the Remote IP and port number can be reported
|
||||
incorrectly in logs and in some circumstances the incorrect server
|
||||
address and port may be used.
|
||||
Often a Connector needs to be configured to accept connections from an intermediary such as a Reverse Proxy and/or Load Balancer deployed in front of the server.
|
||||
In such environments, the TCP/IP connection terminating on the server does not originate from the client, but from the intermediary, so that the Remote IP and port number can be reported incorrectly in logs and in some circumstances the incorrect server address and port may be used.
|
||||
|
||||
Thus Intermediaries typically implement one of several de facto
|
||||
standards to communicate to the server information about the orginal
|
||||
client connection terminating on the intermediary. Jetty supports the
|
||||
`X-Forwarded-For` header and the
|
||||
http://www.haproxy.org/download/1.5/doc/proxy-protocol.txt[Proxy
|
||||
Protocol] mechanisms as described below.
|
||||
Thus Intermediaries typically implement one of several de facto standards to communicate to the server information about the orginal client connection terminating on the intermediary.
|
||||
Jetty supports the `X-Forwarded-For` header and the http://www.haproxy.org/download/1.5/doc/proxy-protocol.txt[Proxy Protocol] mechanisms as described below.
|
||||
|
||||
____
|
||||
[NOTE]
|
||||
|
@ -302,12 +209,8 @@ ____
|
|||
|
||||
===== X-Forward-for Configuration
|
||||
|
||||
The `X-Forwarded-for` header and associated headers are a defacto
|
||||
standard where intermediaries add HTTP headers to each request they
|
||||
forward to describe the originating connection. These headers can be
|
||||
interpreted by an instance of
|
||||
link:{JDURL}/org/eclipse/jetty/server/ForwardedRequestCustomizer.html[`ForwardedRequestCustomizer`]
|
||||
which can be added to a HttpConfiguration as follows:
|
||||
The `X-Forwarded-for` header and associated headers are a de facto standard where intermediaries add HTTP headers to each request they forward to describe the originating connection.
|
||||
These headers can be interpreted by an instance of link:{JDURL}/org/eclipse/jetty/server/ForwardedRequestCustomizer.html[`ForwardedRequestCustomizer`] which can be added to a `HttpConfiguration` as follows:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
|
@ -324,20 +227,12 @@ which can be added to a HttpConfiguration as follows:
|
|||
|
||||
===== Proxy Protocol
|
||||
|
||||
The http://www.haproxy.org/download/1.5/doc/proxy-protocol.txt[Proxy
|
||||
Protocol] is a defacto standard created by HAProxy and used by
|
||||
environments such as Amazon Elastic Cloud. This mechanism is independent
|
||||
of any protocol, so it can be used for HTTP2, TLS etc. The information
|
||||
about the client connection is sent as a small data frame on each newly
|
||||
established connection. In Jetty, this protocol can be handled by the
|
||||
link:{JDURL}/org/eclipse/jetty/server/ProxyConnectionFactory.html[`ProxyConnectionFactory`]
|
||||
which parses the data frame and then instantiates the next
|
||||
ConnectionFactory on the connection with and EndPoint that has been
|
||||
customized with the data obtained about the orginal client connection.
|
||||
The connection factory can be added to any
|
||||
link:{JDURL}/org/eclipse/jetty/server/ServerConnector.html[`ServerConnector`]
|
||||
and should be the first
|
||||
link:{JDURL}/org/eclipse/jetty/server/ConnectionFactory.html[`ConnectionFactory`].
|
||||
The http://www.haproxy.org/download/1.5/doc/proxy-protocol.txt[Proxy Protocol] is a de facto standard created by HAProxy and used by environments such as Amazon Elastic Cloud.
|
||||
This mechanism is independent of any protocol, so it can be used for HTTP2, TLS etc.
|
||||
The information about the client connection is sent as a small data frame on each newly established connection.
|
||||
In Jetty, this protocol can be handled by the link:{JDURL}/org/eclipse/jetty/server/ProxyConnectionFactory.html[`ProxyConnectionFactory`] which parses the data frame and then instantiates the next `ConnectionFactory` on the connection with an end point that has been customized with the data obtained about the original client connection.
|
||||
The connection factory can be added to any link:{JDURL}/org/eclipse/jetty/server/ServerConnector.html[`ServerConnector`] and should be the first link:{JDURL}/org/eclipse/jetty/server/ConnectionFactory.html[`ConnectionFactory`].
|
||||
|
||||
An example of adding the factory to a HTTP connector is:
|
||||
|
||||
[source,xml]
|
||||
|
|
|
@ -17,60 +17,43 @@
|
|||
[[configuring-ssl]]
|
||||
=== Configuring SSL/TLS
|
||||
|
||||
This document provides an overview of how to configure SSL and TLS for
|
||||
Jetty.
|
||||
This document provides an overview of how to configure SSL and TLS for Jetty.
|
||||
|
||||
[[tls-and-ssl-versions]]
|
||||
==== TLS and SSL versions
|
||||
|
||||
Which browser/OS supports which protocols can be
|
||||
https://en.wikipedia.org/wiki/Transport_Layer_Security#Web_browsers[found
|
||||
on Wikipedia]
|
||||
Which browser/OS supports which protocols can be https://en.wikipedia.org/wiki/Transport_Layer_Security#Web_browsers[found on Wikipedia].
|
||||
|
||||
* TLS v1.1 and v1.2: The protocols which should be used wherever
|
||||
possible. All CBC based ciphers are supported since Java 7, the new GCM
|
||||
modes are supported since Java 8.
|
||||
* TLS v1.0: still OK but affected by the POODLE attack too. To support
|
||||
older browsers this protocol version is still needed.
|
||||
* SSL v3: is now deprecated and should only be enabled if you still need
|
||||
to support very old browsers like Internet Explorer 6 on Windows XP
|
||||
which does not support TLS 1.0 (or is disabled by default).
|
||||
* TLS v1.1 and v1.2: The protocols which should be used wherever possible.
|
||||
All CBC based ciphers are supported since Java 7, the new GCM modes are supported since Java 8.
|
||||
* TLS v1.0: still supported but is affected by the POODLE attack.
|
||||
To support older browsers this protocol version is still needed.
|
||||
* SSL v3: is now deprecated and should only be enabled if you still need to support very old browsers like Internet Explorer 6 on Windows XP which does not support TLS 1.0 (or is disabled by default).
|
||||
|
||||
[[understanding-certificates-and-keys]]
|
||||
==== Understanding Certificates and Keys
|
||||
|
||||
Configuring SSL can be a confusing experience of keys, certificates,
|
||||
protocols and formats, thus it helps to have a reasonable understanding
|
||||
of the basics. The following links provide some good starting points:
|
||||
Configuring SSL can be a confusing experience of keys, certificates, protocols and formats, thus it helps to have a reasonable understanding of the basics.
|
||||
The following links provide some good starting points:
|
||||
|
||||
* Certificates:
|
||||
** http://en.tldp.org/HOWTO/SSL-Certificates-HOWTO/index.html[SSL
|
||||
Certificates HOWTO]
|
||||
** http://mindprod.com/jgloss/certificate.html[Mindprod Java Glossary:
|
||||
Certificates]
|
||||
** http://en.tldp.org/HOWTO/SSL-Certificates-HOWTO/index.html[SSL Certificates HOWTO]
|
||||
** http://mindprod.com/jgloss/certificate.html[Mindprod Java Glossary: Certificates]
|
||||
* Keytool:
|
||||
** http://docs.oracle.com/javase/8/docs/technotes/tools/unix/keytool.html[Keytool
|
||||
for Unix]
|
||||
** http://docs.oracle.com/javase/8/docs/technotes/tools/windows/keytool.html[Keytool
|
||||
for Windows]
|
||||
** http://docs.oracle.com/javase/8/docs/technotes/tools/unix/keytool.html[Keytool for Unix]
|
||||
** http://docs.oracle.com/javase/8/docs/technotes/tools/windows/keytool.html[Keytool for Windows]
|
||||
* Other tools:
|
||||
** https://www.ibm.com/developerworks/mydeveloperworks/groups/service/html/communityview?communityUuid=6fb00498-f6ea-4f65-bf0c-adc5bd0c5fcc[IBM
|
||||
Keyman]
|
||||
** https://www.ibm.com/developerworks/mydeveloperworks/groups/service/html/communityview?communityUuid=6fb00498-f6ea-4f65-bf0c-adc5bd0c5fcc[IBM Keyman]
|
||||
* OpenSSL:
|
||||
** http://www.openssl.org/support/faq.html[OpenSSL FAQ]
|
||||
|
||||
[[openssl-vs-keytool]]
|
||||
===== OpenSSL vs. Keytool
|
||||
|
||||
For testing, the `keytool` utility bundled with the JDK provides the
|
||||
simplest way to generate the key and certificate you need.
|
||||
For testing, the `keytool` utility bundled with the JDK provides the simplest way to generate the key and certificate you need.
|
||||
|
||||
You can also use the OpenSSL tools to generate keys and certificates, or
|
||||
to convert those that you have used with Apache or other servers. Since
|
||||
Apache and other servers commonly use the OpenSSL tool suite to generate
|
||||
and manipulate keys and certificates, you might already have some keys
|
||||
and certificates created by OpenSSL, or you might also prefer the
|
||||
formats OpenSSL produces.
|
||||
You can also use the OpenSSL tools to generate keys and certificates, or to convert those that you have used with Apache or other servers.
|
||||
Since Apache and other servers commonly use the OpenSSL tool suite to generate and manipulate keys and certificates, you might already have some keys and certificates created by OpenSSL, or you might also prefer the formats OpenSSL produces.
|
||||
|
||||
If you want the option of using the same certificate with Jetty or a web
|
||||
server such as Apache not written in Java, you might prefer to generate
|
||||
|
@ -79,8 +62,7 @@ your private key and certificate with OpenSSL.
|
|||
[[configuring-jetty-for-ssl]]
|
||||
===== Configuring Jetty for SSL
|
||||
|
||||
To configure Jetty for SSL, complete the tasks in the following
|
||||
sections:
|
||||
To configure Jetty for SSL, complete the tasks in the following sections:
|
||||
|
||||
* xref:generating-key-pairs-and-certificates[]
|
||||
* xref:requesting-trusted-certificate[]
|
||||
|
@ -90,33 +72,28 @@ sections:
|
|||
[[generating-key-pairs-and-certificates]]
|
||||
===== Generating Key Pairs and Certificates
|
||||
|
||||
The simplest way to generate keys and certificates is to use the
|
||||
`keytool` application that comes with the JDK, as it generates keys and
|
||||
certificates directly into the keystore. See
|
||||
xref:generating-key-pairs-and-certificates-JDK-keytool[].
|
||||
The simplest way to generate keys and certificates is to use the `keytool` application that comes with the JDK, as it generates keys and certificates directly into the keystore.
|
||||
See xref:generating-key-pairs-and-certificates-JDK-keytool[].
|
||||
|
||||
If you already have keys and certificates, see
|
||||
xref:loading-keys-and-certificates[] to load them into a
|
||||
JSSE keystore. This section also applies if you have a renewal
|
||||
certificate to replace one that is expiring.
|
||||
If you already have keys and certificates, see xref:loading-keys-and-certificates[] to load them into a JSSE keystore.
|
||||
This section also applies if you have a renewal certificate to replace one that is expiring.
|
||||
|
||||
The examples below generate only basic keys and certificates. You should
|
||||
read the full manuals of the tools you are using if you want to specify:
|
||||
The examples below generate only basic keys and certificates.
|
||||
You should read the full manuals of the tools you are using if you want to specify:
|
||||
|
||||
* the key size
|
||||
* the certificate expiration date
|
||||
* alternate security providers
|
||||
* The key size
|
||||
* The certificate expiration date
|
||||
* Alternate security providers
|
||||
|
||||
[[generating-key-pairs-and-certificates-JDK-keytool]]
|
||||
====== Generating Keys and Certificates with JDK's keytool
|
||||
|
||||
The following command generates a key pair and certificate directly into
|
||||
file `keystore`:
|
||||
The following command generates a key pair and certificate directly into file `keystore`:
|
||||
|
||||
[source, screen]
|
||||
....
|
||||
----
|
||||
$ keytool -keystore keystore -alias jetty -genkey -keyalg RSA
|
||||
....
|
||||
----
|
||||
|
||||
____
|
||||
[NOTE]
|
||||
|
@ -125,13 +102,12 @@ In a browser, it displays a message "Could not establish an encrypted connection
|
|||
The solution is to use RSA for the key algorithm.
|
||||
____
|
||||
|
||||
This command prompts for information about the certificate and for
|
||||
passwords to protect both the keystore and the keys within it. The only
|
||||
mandatory response is to provide the fully qualified host name of the
|
||||
server at the "first and last name" prompt. For example:
|
||||
This command prompts for information about the certificate and for passwords to protect both the keystore and the keys within it.
|
||||
The only mandatory response is to provide the fully qualified host name of the server at the "first and last name" prompt.
|
||||
For example:
|
||||
|
||||
[source, screen]
|
||||
....
|
||||
----
|
||||
$ keytool -keystore keystore -alias jetty -genkey -keyalg RSA -sigalg SHA256withRSA
|
||||
Enter keystore password: password
|
||||
What is your first and last name?
|
||||
|
@ -153,28 +129,21 @@ $ keytool -keystore keystore -alias jetty -genkey -keyalg RSA -sigalg SHA256with
|
|||
Enter key password for <jetty>
|
||||
(RETURN if same as keystore password):
|
||||
$
|
||||
....
|
||||
----
|
||||
|
||||
You now have the minimal requirements to run an SSL connection and could
|
||||
proceed directly to link:#configuring-sslcontextfactory[configure an SSL
|
||||
connector]. However the browser will not trust the certificate you have
|
||||
generated, and prompts the user to this effect. While what you have at
|
||||
this point is often sufficient for testing, most public sites need a
|
||||
trusted certificate, as shown in the section
|
||||
link:#generating-csr-from-keytool[generating a CSR with keytool].
|
||||
You now have the minimal requirements to run an SSL connection and could proceed directly to link:#configuring-sslcontextfactory[configure an SSL connector].
|
||||
However, the browser will not trust the certificate you have generated, and prompts the user to this effect.
|
||||
While what you have at this point is often sufficient for testing, most public sites need a trusted certificate, as shown in the section link:#generating-csr-from-keytool[generating a CSR with keytool].
|
||||
|
||||
If you want to use only a self signed certificate for some kind of
|
||||
internal admin panel add -validity <days> to the keytool call above,
|
||||
otherwise your certificate is only valid for one month.
|
||||
If you want to use only a self signed certificate for some kind of internal admin panel add -validity <days> to the keytool call above, otherwise your certificate is only valid for one month.
|
||||
|
||||
If you are using java 8 or later, then you may also use the SAN
|
||||
extension to set one or more names that the certificate applies to:
|
||||
If you are using Java 8 or later, then you may also use the SAN extension to set one or more names that the certificate applies to:
|
||||
|
||||
[source, screen]
|
||||
....
|
||||
----
|
||||
$ keytool -keystore keystore -alias jetty -genkey -keyalg RSA -sigalg SHA256withRSA -ext 'SAN=dns:jetty.eclipse.org,dns:*.jetty.org'
|
||||
...
|
||||
....
|
||||
----
|
||||
|
||||
[[generating-keys-and-certificates-openssl]]
|
||||
====== Generating Keys and Certificates with OpenSSL
|
||||
|
@ -182,32 +151,27 @@ $ keytool -keystore keystore -alias jetty -genkey -keyalg RSA -sigalg SHA256with
|
|||
The following command generates a key pair in the file `jetty.key`:
|
||||
|
||||
[source, screen]
|
||||
....
|
||||
----
|
||||
$ openssl genrsa -aes128 -out jetty.key
|
||||
....
|
||||
----
|
||||
|
||||
You might also want to use the `-rand` file argument to provide an
|
||||
arbitrary file that helps seed the random number generator.
|
||||
You might also want to use the `-rand` file argument to provide an arbitrary file that helps seed the random number generator.
|
||||
|
||||
The following command generates a certificate for the key into the file
|
||||
` jetty.crt`:
|
||||
The following command generates a certificate for the key into the file `jetty.crt`:
|
||||
|
||||
[source, screen]
|
||||
....
|
||||
----
|
||||
$ openssl req -new -x509 -newkey rsa:2048 -sha256 -key jetty.key -out jetty.crt
|
||||
....
|
||||
----
|
||||
|
||||
Adding -sha256 ensures to get a certificate with the now recommended
|
||||
SHA-256 signature algorithm. For the paranoid ones add -b4096 to get a
|
||||
4069bits long key.
|
||||
Adding -sha256 ensures to get a certificate with the now recommended SHA-256 signature algorithm.
|
||||
For the those with heightened security in mind, add -b4096 to get a 4069 bit key.
|
||||
|
||||
The next command prompts for information about the certificate and for
|
||||
passwords to protect both the keystore and the keys within it. The only
|
||||
mandatory response is to provide the fully qualified host name of the
|
||||
server at the "Common Name" prompt. For example:
|
||||
The next command prompts for information about the certificate and for passwords to protect both the keystore and the keys within it.
|
||||
The only mandatory response is to provide the fully qualified host name of the server at the "Common Name" prompt. For example:
|
||||
|
||||
[source, screen]
|
||||
....
|
||||
----
|
||||
$ openssl genrsa -aes128 -out jetty.key
|
||||
Generating RSA private key, 2048 bit long modulus
|
||||
..............+++
|
||||
|
@ -218,13 +182,12 @@ Verifying - Enter pass phrase for jetty.key:
|
|||
|
||||
$ openssl req -new -x509 -newkey rsa:2048 -sha256 -key jetty.key -out jetty.crt
|
||||
Enter pass phrase for jetty.key:
|
||||
You are about to be asked to enter information that will be incorporated
|
||||
into your certificate request.
|
||||
You are about to be asked to enter information that will be incorporated into your certificate request.
|
||||
What you are about to enter is what is called a Distinguished Name or a DN.
|
||||
There are quite a few fields but you can leave some blank
|
||||
For some fields there will be a default value,
|
||||
There are quite a few fields but you can leave some blank.
|
||||
For some fields there will be a default value.
|
||||
If you enter '.', the field will be left blank.
|
||||
-----
|
||||
|
||||
Country Name (2 letter code) [AU]:
|
||||
State or Province Name (full name) [Some-State]:
|
||||
Locality Name (eg, city) []:
|
||||
|
@ -234,89 +197,68 @@ Common Name (e.g. server FQDN or YOUR name) []:jetty.eclipse.org
|
|||
Email Address []:
|
||||
|
||||
$
|
||||
....
|
||||
----
|
||||
|
||||
You now have the minimal requirements to run an SSL connection and could
|
||||
proceed directly to xref:loading-keys-and-certificates[]
|
||||
to load these keys and certificates into a JSSE keystore. However the
|
||||
browser will not trust the certificate you have generated, and prompts
|
||||
the user to this effect. While what you have at this point is often
|
||||
sufficient for testing, most public sites need a trusted certificate, as
|
||||
shown in the section, xref:generating-csr-from-openssl[]
|
||||
to obtain a certificate.
|
||||
You now have the minimal requirements to run an SSL connection and could proceed directly to xref:loading-keys-and-certificates[] to load these keys and certificates into a JSSE keystore.
|
||||
However the browser will not trust the certificate you have generated, and prompts the user to this effect.
|
||||
While what you have at this point is often sufficient for testing, most public sites need a trusted certificate, as shown in the section, xref:generating-csr-from-openssl[] to obtain a certificate.
|
||||
|
||||
[[using-keys-and-certificates-from-other-sources]]
|
||||
====== Using Keys and Certificates from Other Sources
|
||||
|
||||
If you have keys and certificates from other sources, you can proceed
|
||||
directly to xref:loading-keys-and-certificates[].
|
||||
If you have keys and certificates from other sources, you can proceed directly to xref:loading-keys-and-certificates[].
|
||||
|
||||
[[requesting-trusted-certificate]]
|
||||
===== Requesting a Trusted Certificate
|
||||
|
||||
The keys and certificates generated with JDK's `keytool` and OpenSSL are
|
||||
sufficient to run an SSL connector. However the browser will not trust
|
||||
the certificate you have generated, and it will prompt the user to this
|
||||
effect.
|
||||
The keys and certificates generated with JDK's `keytool` and OpenSSL are sufficient to run an SSL connector.
|
||||
However the browser will not trust the certificate you have generated, and it will prompt the user to this effect.
|
||||
|
||||
To obtain a certificate that most common browsers will trust, you need
|
||||
to request a well-known certificate authority (CA) to sign your
|
||||
key/certificate. Such trusted CAs include: AddTrust, Entrust, GeoTrust,
|
||||
RSA Data Security, Thawte, VISA, ValiCert, Verisign, and beTRUSTed,
|
||||
among others. Each CA has its own instructions (look for JSSE or OpenSSL
|
||||
sections), but all involve a step that generates a certificate signing
|
||||
request (CSR).
|
||||
To obtain a certificate that most common browsers will trust, you need to request a well-known certificate authority (CA) to sign your key/certificate.
|
||||
Such trusted CAs include: AddTrust, Entrust, GeoTrust, RSA Data Security, Thawte, VISA, ValiCert, Verisign, and beTRUSTed, among others.
|
||||
Each CA has its own instructions (look for JSSE or OpenSSL sections), but all involve a step that generates a certificate signing request (CSR).
|
||||
|
||||
[[generating-csr-from-keytool]]
|
||||
====== Generating a CSR with keytool
|
||||
|
||||
The following command generates the file `jetty.csr` using `keytool` for
|
||||
a key/cert already in the keystore:
|
||||
The following command generates the file `jetty.csr` using `keytool` for a key/cert already in the keystore:
|
||||
|
||||
[source, screen]
|
||||
....
|
||||
----
|
||||
$ keytool -certreq -alias jetty -keystore keystore -file jetty.csr
|
||||
....
|
||||
----
|
||||
|
||||
[[generating-csr-from-openssl]]
|
||||
====== Generating a CSR from OpenSSL
|
||||
|
||||
The following command generates the file `jetty.csr` using OpenSSL for a
|
||||
key in the file `jetty.key`:
|
||||
The following command generates the file `jetty.csr` using OpenSSL for a key in the file `jetty.key`:
|
||||
|
||||
[source, screen]
|
||||
....
|
||||
----
|
||||
$ openssl req -new -key jetty.key -out jetty.csr
|
||||
....
|
||||
----
|
||||
|
||||
Notice that this command uses only the existing key from `jetty.key`
|
||||
file, and not a certificate in `jetty.crt` as generated with OpenSSL.
|
||||
Notice that this command uses only the existing key from `jetty.key` file, and not a certificate in `jetty.crt` as generated with OpenSSL.
|
||||
You need to enter the details for the certificate again.
|
||||
|
||||
[[loading-keys-and-certificates]]
|
||||
===== Loading Keys and Certificates
|
||||
|
||||
Once a CA has sent you a certificate, or if you generated your own
|
||||
certificate without `keytool`, you need to load it into a JSSE keystore.
|
||||
Once a CA has sent you a certificate, or if you generated your own certificate without `keytool`, you need to load it into a JSSE keystore.
|
||||
|
||||
____
|
||||
[NOTE]
|
||||
You need both the private key and the certificate in the JSSE keystore.
|
||||
You should load the certificate into the keystore used to generate the
|
||||
CSR with `keytool`. If your key pair is not already in a keystore (for
|
||||
example, because it has been generated with OpenSSL), you need to use
|
||||
the PKCS12 format to load both key and certificate (see
|
||||
link:#loading-keys-and-certificates-via-pkcks12[PKCKS12 Keys &
|
||||
Certificates]).
|
||||
You should load the certificate into the keystore used to generate the CSR with `keytool`.
|
||||
If your key pair is not already in a keystore (for example, because it has been generated with OpenSSL), you need to use the PKCS12 format to load both key and certificate (see link:#loading-keys-and-certificates-via-pkcks12[PKCKS12 Keys &Certificates]).
|
||||
____
|
||||
|
||||
[[loading-certificates-with-keytool]]
|
||||
====== Loading Certificates with keytool
|
||||
|
||||
You can use `keytool` to load a certificate in PEM form directly into a
|
||||
keystore. The PEM format is a text encoding of certificates; it is
|
||||
produced by OpenSSL, and is returned by some CAs. An example PEM file
|
||||
is:
|
||||
You can use `keytool` to load a certificate in PEM form directly into a keystore.
|
||||
The PEM format is a text encoding of certificates; it is produced by OpenSSL, and is returned by some CAs.
|
||||
An example PEM file is:
|
||||
|
||||
....
|
||||
jetty.crt
|
||||
|
@ -337,159 +279,118 @@ Rcz6oCRvCGCe5kDB
|
|||
-----END CERTIFICATE-----
|
||||
....
|
||||
|
||||
The following command loads a PEM encoded certificate in the `jetty.crt`
|
||||
file into a JSSE keystore:
|
||||
The following command loads a PEM encoded certificate in the `jetty.crt` file into a JSSE keystore:
|
||||
|
||||
[source, screen]
|
||||
....
|
||||
----
|
||||
$ keytool -keystore keystore -import -alias jetty -file jetty.crt -trustcacerts
|
||||
....
|
||||
----
|
||||
|
||||
If the certificate you receive from the CA is not in a format that
|
||||
`keytool` understands, you can use the `openssl` command to convert
|
||||
formats:
|
||||
If the certificate you receive from the CA is not in a format that `keytool` understands, you can use the `openssl` command to convert formats:
|
||||
|
||||
[source, screen]
|
||||
....
|
||||
----
|
||||
$ openssl x509 -in jetty.der -inform DER -outform PEM -out jetty.crt
|
||||
....
|
||||
----
|
||||
|
||||
[[loading-keys-and-certificates-via-pkcks12]]
|
||||
====== Loading Keys and Certificates via PKCS12
|
||||
|
||||
If you have a key and certificate in separate files, you need to combine
|
||||
them into a PKCS12 format file to load into a new keystore. The
|
||||
certificate can be one you generated yourself or one returned from a CA
|
||||
in response to your CSR.
|
||||
If you have a key and certificate in separate files, you need to combine them into a PKCS12 format file to load into a new keystore.
|
||||
The certificate can be one you generated yourself or one returned from a CA in response to your CSR.
|
||||
|
||||
The following OpenSSL command combines the keys in `jetty.key` and the
|
||||
certificate in the `jetty.crt` file into the `jetty.pkcs12` file:
|
||||
The following OpenSSL command combines the keys in `jetty.key` and the certificate in the `jetty.crt` file into the `jetty.pkcs12` file:
|
||||
|
||||
[source, screen]
|
||||
....
|
||||
----
|
||||
$ openssl pkcs12 -inkey jetty.key -in jetty.crt -export -out jetty.pkcs12
|
||||
....
|
||||
----
|
||||
|
||||
If you have a chain of certificates, because your CA is an intermediary,
|
||||
build the PKCS12 file as follows:
|
||||
If you have a chain of certificates, because your CA is an intermediary, build the PKCS12 file as follows:
|
||||
|
||||
[source, screen]
|
||||
....
|
||||
----
|
||||
$ cat example.crt intermediate.crt [intermediate2.crt] ... rootCA.crt > cert-chain.txt
|
||||
$ openssl pkcs12 -export -inkey example.key -in cert-chain.txt -out example.pkcs12
|
||||
....
|
||||
----
|
||||
|
||||
The order of certificates must be from server to rootCA, as per RFC2246
|
||||
section 7.4.2.
|
||||
The order of certificates must be from server to rootCA, as per RFC2246 section 7.4.2.
|
||||
|
||||
OpenSSL asks for an __export password__. A non-empty password is
|
||||
required to make the next step work. Then load the resulting PKCS12 file
|
||||
into a JSSE keystore with `keytool`:
|
||||
OpenSSL asks for an __export password__.
|
||||
A non-empty password is required to make the next step work.
|
||||
Then load the resulting PKCS12 file into a JSSE keystore with `keytool`:
|
||||
|
||||
[source, screen]
|
||||
....
|
||||
----
|
||||
$ keytool -importkeystore -srckeystore jetty.pkcs12 -srcstoretype PKCS12 -destkeystore keystore
|
||||
....
|
||||
----
|
||||
|
||||
[[renewing-certificates]]
|
||||
===== Renewing Certificates
|
||||
|
||||
If you are updating your configuration to use a newer certificate, as
|
||||
when the old one is expiring, just load the newer certificate as
|
||||
described in the section,
|
||||
xref:loading-keys-and-certificates[]. If you imported the
|
||||
key and certificate originally using the PKCS12 method, use an alias of
|
||||
"1" rather than "jetty", because that is the alias the PKCS12 process
|
||||
enters into the keystore.
|
||||
If you are updating your configuration to use a newer certificate, as when the old one is expiring, just load the newer certificate as described in the section, xref:loading-keys-and-certificates[].
|
||||
If you imported the key and certificate originally using the PKCS12 method, use an alias of "1" rather than "jetty", because that is the alias the PKCS12 process enters into the keystore.
|
||||
|
||||
[[configuring-sslcontextfactory]]
|
||||
==== Configuring the Jetty SslContextFactory
|
||||
==== Configuring the Jetty `SslContextFactory`
|
||||
|
||||
The generated SSL certificates from above are held in the key store are
|
||||
configured in an instance of
|
||||
link:{JDURL}/org/eclipse/jetty/util/ssl/SslContextFactory.html[SslContextFactory]
|
||||
object.
|
||||
The generated SSL certificates from above are held in the key store are configured in an instance of link:{JDURL}/org/eclipse/jetty/util/ssl/SslContextFactory.html[SslContextFactory] object.
|
||||
|
||||
The SslContextFactory is responsible for:
|
||||
The `SslContextFactory` is responsible for:
|
||||
|
||||
* Creating the Java `SslEngine` used by Jetty's Connectors and Jetty's
|
||||
Clients (HTTP/1, HTTP/2, and WebSocket).
|
||||
* Creating the Java `SslEngine` used by Jetty's Connectors and Jetty's Clients (HTTP/1, HTTP/2, and WebSocket).
|
||||
* Managing Keystore Access
|
||||
* Managing Truststore Access
|
||||
* Managing Protocol selection via Excludes / Includes list
|
||||
* Managing Cipher Suite selection via Excludes / Includes list
|
||||
* Managing order of Ciphers offered (important for TLS/1.2 and HTTP/2
|
||||
support)
|
||||
* Managing order of Ciphers offered (important for TLS/1.2 and HTTP/2 support)
|
||||
* SSL Session Caching options
|
||||
* Certificate https://en.wikipedia.org/wiki/Revocation_list[Revocation
|
||||
Lists] and Distribution Points (CRLDP)
|
||||
* https://en.wikipedia.org/wiki/Online_Certificate_Status_Protocol[OCSP]
|
||||
Support
|
||||
* Certificate https://en.wikipedia.org/wiki/Revocation_list[Revocation Lists] and Distribution Points (CRLDP)
|
||||
* https://en.wikipedia.org/wiki/Online_Certificate_Status_Protocol[OCSP] Support
|
||||
* Client Authentication Support
|
||||
|
||||
For Jetty Connectors, the configured `SslContextFactory` is injected
|
||||
into a specific `ServerConnector` `SslConnectionFactory`.
|
||||
For Jetty Connectors, the configured `SslContextFactory` is injected into a specific `ServerConnector` `SslConnectionFactory`.
|
||||
|
||||
For Jetty Clients, the various constructors support using a configured
|
||||
`SslContextFactory`.
|
||||
For Jetty Clients, the various constructors support using a configured `SslContextFactory`.
|
||||
|
||||
While the SslContextFactory can operate without a keystore (this mode is
|
||||
most suitable for the various Jetty Clients) it is best if you at least
|
||||
configure the Keystore you are using.
|
||||
While the `SslContextFactory` can operate without a keystore (this mode is most suitable for the various Jetty Clients) it is best if you at least configure the keystore you are using.
|
||||
|
||||
setKeyStorePath::
|
||||
The configured keystore to use for all SSL/TLS in configured Jetty
|
||||
Connector (or Client).
|
||||
+
|
||||
The configured keystore to use for all SSL/TLS in configured Jetty Connector (or Client).
|
||||
____
|
||||
[NOTE]
|
||||
as a keystore is vital security information, it can be desirable to locate the file in a directory with very restricted access.
|
||||
As a keystore is vital security information, it can be desirable to locate the file in a directory with very restricted access.
|
||||
____
|
||||
|
||||
setKeyStorePassword::
|
||||
The keystore password may be set here in plain text, or as some
|
||||
protection from casual observation, it may be obfuscated using the
|
||||
link:{JDURL}/org/eclipse/jetty/util/security/Password.html[Password]
|
||||
class.
|
||||
The keystore password may be set here in plain text, or as some protection from casual observation, it may be obfuscated using the link:{JDURL}/org/eclipse/jetty/util/security/Password.html[Password] class.
|
||||
setTrustStorePath::
|
||||
This is used if validating client certificates and is typically set to
|
||||
the same path as the keystore.
|
||||
This is used if validating client certificates and is typically set to the same path as the keystore.
|
||||
setKeyManagerPassword::
|
||||
is a password that is passed to the `KeyManagerFactory.init(...)`. If
|
||||
there is no keymanagerpassword, then the keystorepassword is used
|
||||
instead. If there is no trustmanager set, then the keystore is used as
|
||||
the trust store and the keystorepassword is used as the truststore
|
||||
password
|
||||
Password that is passed to the `KeyManagerFactory.init(...)`.
|
||||
If there is no `keymanagerpassword`, then the `keystorepassword` is used instead.
|
||||
If there is no `trustmanager` set, then the keystore is used as the trust store and the `keystorepassword` is used as the truststore password.
|
||||
setExcludeCipherSuites / setIncludeCipherSuites::
|
||||
This allows for the customization of the selected Cipher Suites that
|
||||
will be used by SSL/TLS
|
||||
This allows for the customization of the selected Cipher Suites that will be used by SSL/TLS.
|
||||
setExcludeProtocols / setIncludeProtocols::
|
||||
This allows for the customization of the selected Protocols that will
|
||||
be used by SSL/TLS
|
||||
This allows for the customization of the selected Protocols that will be used by SSL/TLS.
|
||||
|
||||
____
|
||||
[NOTE]
|
||||
When working with Includes / Excludes, it is important to know that Excludes will always win.
|
||||
+
|
||||
The selection process is to process the JVM list of available Cipher Suites or Protocols against the include list, then remove the excluded ones.
|
||||
+
|
||||
Be aware that each Include / Exclude list has a Set method (replace the
|
||||
list) or Add method (append the list)
|
||||
Be aware that each Include / Exclude list has a Set method (replace the list) or Add method (append the list).
|
||||
____
|
||||
|
||||
____
|
||||
[CAUTION]
|
||||
The key and truststore passwords may also be set using the system properties: `org.eclipse.jetty.ssl.keypassword` `org.eclipse.jetty.ssl.password`.
|
||||
+
|
||||
This is _not_ a recommended usage.
|
||||
____
|
||||
|
||||
==== Configuring SSL in Jetty Distribution
|
||||
|
||||
For those of you using the Jetty Distribution, the provided modules for
|
||||
https and http2 will automatically setup the SslContextFactory, the
|
||||
appropriate SslConnectionFactory, and associated ServerConnectors for
|
||||
you, in the correct order.
|
||||
For those of you using the Jetty Distribution, the provided modules for https and http2 will automatically setup the `SslContextFactory`, the appropriate `SslConnectionFactory`, and associated `ServerConnectors` for you in the correct order.
|
||||
|
||||
An example of this setup:
|
||||
|
||||
|
@ -507,53 +408,36 @@ $ ls -l etc
|
|||
-rw-rw-r--. 1 user group 3697 Feb 2 11:47 keystore
|
||||
----
|
||||
|
||||
When you check your start.ini, you'll see many commented properties
|
||||
ready for you to configure the SslContextFactory basics.
|
||||
When you check the `start.ini`, you'll see many commented properties ready for you to configure the `SslContextFactory` basics.
|
||||
|
||||
To highlight some of the more commonly used properties:
|
||||
|
||||
jetty.ssl.host::
|
||||
Configures which interfaces the SSL/TLS Connector should listen on
|
||||
Configures which interfaces the SSL/TLS Connector should listen on.
|
||||
jetty.ssl.port::
|
||||
Configures which port the SSL/TLS Connector should listen on
|
||||
Configures which port the SSL/TLS Connector should listen on.
|
||||
jetty.httpConfig.securePort::
|
||||
If a webapp needs to redirect to a secure version of the same
|
||||
resource, then this is the port reported back on the Response
|
||||
`Location` line (Having this be separate is useful if you have
|
||||
something sitting in front of Jetty, such as a Load Balancer or proxy)
|
||||
If a webapp needs to redirect to a secure version of the same resource, then this is the port reported back on the response `location` line (having this be separate is useful if you have something sitting in front of Jetty, such as a Load Balancer or proxy).
|
||||
jetty.sslContext.keyStorePath::
|
||||
Sets the location of the `keystore` that you configured with your
|
||||
certificates
|
||||
Sets the location of the `keystore` that you configured with your certificates.
|
||||
jetty.sslContext.keyStorePassword::
|
||||
Sets the Password for the `keystore`
|
||||
Sets the Password for the `keystore`.
|
||||
|
||||
==== Configuring SNI
|
||||
|
||||
From java8, the JVM contains support for the
|
||||
http://en.wikipedia.org/wiki/Server_Name_Indication[Server Name
|
||||
Indicator (SNI)] extension, which allows a SSL connection handshake to
|
||||
indicate one or more DNS names that it applies to. To support this, the
|
||||
ExtendedSslContextFactory is used that will look for multiple X509
|
||||
certificates within the keystore, each of which may have multiple DNS
|
||||
names (including wildcards) associated with the
|
||||
http://en.wikipedia.org/wiki/SubjectAltName[Subject Alternate Name]
|
||||
extension. When using the ExtendedSSlContextFactory, the correct
|
||||
certificate is automatically selected if the SNI extension is present in
|
||||
the handshake.
|
||||
From Java 8, the JVM contains support for the http://en.wikipedia.org/wiki/Server_Name_Indication[Server Name Indicator (SNI)] extension, which allows a SSL connection handshake to indicate one or more DNS names that it applies to.
|
||||
To support this, the `ExtendedSslContextFactory` is used that will look for multiple X509 certificates within the keystore, each of which may have multiple DNS names (including wildcards) associated with the http://en.wikipedia.org/wiki/SubjectAltName[Subject Alternate Name] extension.
|
||||
When using the `ExtendedSSlContextFactory`, the correct certificate is automatically selected if the SNI extension is present in the handshake.
|
||||
|
||||
[[configuring-sslcontextfactory-cipherSuites]]
|
||||
==== Disabling/Enabling Specific Cipher Suites
|
||||
|
||||
For example to avoid the BEAST attack it is necessary to configure a
|
||||
specific set of cipher suites. This can either be done via
|
||||
link:{JDURL}/org/eclipse/jetty/util/ssl/SslContextFactory.html#setIncludeCipherSuites(java.lang.String...)[SslContext.setIncludeCipherSuites(java.lang.String...)]
|
||||
or
|
||||
vialink:{JDURL}/org/eclipse/jetty/util/ssl/SslContextFactory.html#setExcludeCipherSuites(java.lang.String...)[SslContext.setExcludeCipherSuites(java.lang.String...)].
|
||||
For example to avoid the BEAST attack it is necessary to configure a specific set of cipher suites. This can either be done via link:{JDURL}/org/eclipse/jetty/util/ssl/SslContextFactory.html#setIncludeCipherSuites(java.lang.String...)[SslContext.setIncludeCipherSuites(java.lang.String...)] or vialink:{JDURL}/org/eclipse/jetty/util/ssl/SslContextFactory.html#setExcludeCipherSuites(java.lang.String...)[SslContext.setExcludeCipherSuites(java.lang.String...)].
|
||||
|
||||
____
|
||||
[NOTE]
|
||||
It's crucial that you use the exact names of the cipher suites as used/known by the JDK.
|
||||
You can get them by obtaining an instance of SSLEngine and call getSupportedCipherSuites().
|
||||
You can get them by obtaining an instance of SSLEngine and call `getSupportedCipherSuites()`.
|
||||
Tools like ssllabs.com might report slightly different names which will be ignored.
|
||||
____
|
||||
|
||||
|
@ -561,19 +445,14 @@ ____
|
|||
[NOTE]
|
||||
It's recommended to install the Java Cryptography Extension (JCE) Unlimited Strength policy files in your JRE to get full strength ciphers like AES-256.
|
||||
They can be found on the http://www.oracle.com/technetwork/java/javase/downloads/index.html[Java download page].
|
||||
Just overwrite the two present JAR files in `<JRE_HOME>/lib/security/`
|
||||
Just overwrite the two present JAR files in `<JRE_HOME>/lib/security/`.
|
||||
____
|
||||
|
||||
Both setIncludeCipherSuites and setExcludeCipherSuites can be feed by
|
||||
the exact cipher suite name used in the JDK or by using regular
|
||||
expressions.
|
||||
Both `setIncludeCipherSuites` and `setExcludeCipherSuites` can be fed by the exact cipher suite name used in the JDK or by using regular expressions.
|
||||
|
||||
If you have a need to adjust the Includes or Excludes, then this is best
|
||||
done with a custom blow-in XML that configures the SslContextFactory to
|
||||
suit your needs.
|
||||
If you have a need to adjust the Includes or Excludes, then this is best done with a custom blow-in XML that configures the `SslContextFactory` to suit your needs.
|
||||
|
||||
To do this, first create a new `${jetty.base}/etc/tweak-ssl.xml` (this
|
||||
can be any name, just avoid prefixing it with "jetty-")
|
||||
To do this, first create a new `${jetty.base}/etc/tweak-ssl.xml` (thiscan be any name, just avoid prefixing it with "jetty-").
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
|
@ -594,14 +473,10 @@ can be any name, just avoid prefixing it with "jetty-")
|
|||
</Configure>
|
||||
----
|
||||
|
||||
This new XML will configure the id `sslContextFactory` some more (this
|
||||
id is first created by the `ssl` module and its associated
|
||||
`${jetty.home}/etc/jetty-ssl-context.xml`). You can do anything you want
|
||||
with the `SslContextFactory` in use by the Jetty Distribution from this
|
||||
tweak XML.
|
||||
This new XML will configure the id `sslContextFactory` some more (this id is first created by the `ssl` module and its associated `${jetty.home}/etc/jetty-ssl-context.xml`).
|
||||
You can do anything you want with the `SslContextFactory` in use by the Jetty Distribution from this tweaked XML.
|
||||
|
||||
To make sure that your `${jetty.base}` uses this new XML, add it to the
|
||||
end of your `${jetty.base}/start.ini`
|
||||
To make sure that your `${jetty.base}` uses this new XML, add it to the end of your `${jetty.base}/start.ini`
|
||||
|
||||
[source,plain]
|
||||
----
|
||||
|
@ -618,24 +493,19 @@ $
|
|||
|
||||
____
|
||||
[NOTE]
|
||||
The default SslContextFactory implementation applies the latest SSL/TLS recommendations surrounding vulnerabilities in SSL/TLS.
|
||||
The default `SslContextFactory` implementation applies the latest SSL/TLS recommendations surrounding vulnerabilities in SSL/TLS.
|
||||
Check the release notes (The `VERSION.txt` found in the root of the Jetty Distribution, or the http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22org.eclipse.jetty%22%20AND%20a%3A%22jetty-project%22[alternate (classified 'version') artifacts for the `jetty-project` component]on Maven Central) for updates.
|
||||
+
|
||||
The Java JVM is also applying exclusions at the JVM level, and as such, if you have a need to enable something that is generally accepted by the industry as being insecure or vulnerable you will likely have to enable it in BOTH the Java JVM and the Jetty configuration.
|
||||
____
|
||||
|
||||
____
|
||||
[TIP]
|
||||
You can enable the `org.eclipse.jetty.util.ssl` named logger at DEBUG
|
||||
level to see what the list of selected Protocols and Cipher suites are
|
||||
at startup of Jetty.
|
||||
You can enable the `org.eclipse.jetty.util.ssl` named logger at DEBUG level to see what the list of selected Protocols and Cipher suites are at startup of Jetty.
|
||||
____
|
||||
|
||||
Some other Include / Exclude examples:
|
||||
|
||||
Example: Include all ciphers which support
|
||||
https://en.wikipedia.org/wiki/Forward_secrecy[Forward Secrecy] using
|
||||
regex:
|
||||
Example: Include all ciphers which support https://en.wikipedia.org/wiki/Forward_secrecy[Forward Secrecy] using regex:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
|
@ -649,7 +519,7 @@ regex:
|
|||
</Set>
|
||||
----
|
||||
|
||||
Example: Exclude all old, insecure or anonymous cipher suites:
|
||||
*Example*: Exclude all old, insecure or anonymous cipher suites:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
|
@ -667,7 +537,7 @@ Example: Exclude all old, insecure or anonymous cipher suites:
|
|||
</Call>
|
||||
----
|
||||
|
||||
Example: Since 2014 SSLv3 is considered insecure and should be disabled.
|
||||
*Example*: Since 2014 SSLv3 is considered insecure and should be disabled.
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
|
@ -689,7 +559,7 @@ ____
|
|||
Note that disabling SSLv3 prevents very old browsers like Internet Explorer 6 on Windows XP from connecting.
|
||||
____
|
||||
|
||||
Example: TLS renegotiation could be disabled too to prevent an attack based on this feature.
|
||||
*Example*: TLS renegotiation could be disabled too to prevent an attack based on this feature.
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
|
|
|
@ -17,87 +17,61 @@
|
|||
[[setting-port80-access]]
|
||||
=== Setting Port 80 Access for a Non-Root User
|
||||
|
||||
On Unix-based systems, port 80 is protected; typically only the
|
||||
superuser root can open it. For security reasons, it is not desirable to
|
||||
run the server as root. This page presents several options to access
|
||||
port 80 as a non-root user, including using ipchains, iptables, Jetty's
|
||||
SetUID feature, xinetd, and the Solaris 10 User Rights Management
|
||||
Framework.
|
||||
On Unix-based systems, port 80 is protected; typically only the superuser root can open it. For security reasons, it is not desirable to run the server as root.
|
||||
This page presents several options to access port 80 as a non-root user, including using ipchains, iptables, Jetty's SetUID feature, xinetd, and the Solaris 10 User Rights Management Framework.
|
||||
|
||||
[[using-ipchains]]
|
||||
==== Using ipchains
|
||||
|
||||
On some Linux systems you can use the _ipchains REDIRECT_ mechanism to
|
||||
redirect from one port to another inside the kernel (if ipchains is not
|
||||
available, then usually iptables is):
|
||||
On some Linux systems you can use the _ipchains REDIRECT_ mechanism to redirect from one port to another inside the kernel (if ipchains is not available, then usually iptables is):
|
||||
|
||||
[source, screen]
|
||||
....
|
||||
----
|
||||
# /sbin/ipchains -I input --proto TCP --dport 80 -j REDIRECT 8080
|
||||
....
|
||||
----
|
||||
|
||||
This command instructs the system as follows: "Insert into the kernel's
|
||||
packet filtering the following as the first rule to check on incoming
|
||||
packets: if the protocol is TCP and the destination port is 80, redirect
|
||||
the packet to port 8080". Be aware that your kernel must be compiled
|
||||
with support for ipchains (virtually all stock kernels are). You must
|
||||
also have the ipchains command-line utility installed. You can run this
|
||||
command at any time, preferably just once, since it inserts another copy
|
||||
of the rule every time you run it.
|
||||
This command instructs the system as follows: "Insert into the kernel's packet filtering the following as the first rule to check on incoming packets: if the protocol is TCP and the destination port is 80, redirect the packet to port 8080".
|
||||
Be aware that your kernel must be compiled with support for ipchains (virtually all stock kernels are).
|
||||
You must also have the ipchains command-line utility installed.
|
||||
You can run this command at any time, preferably just once, since it inserts another copy of the rule every time you run it.
|
||||
|
||||
[[using-iptables]]
|
||||
==== Using iptables
|
||||
|
||||
On many Linux systems you can use the iptables REDIRECT mechanism to
|
||||
redirect from one port to another inside the kernel (if iptables is not
|
||||
available, then usually ipchains is).
|
||||
On many Linux systems you can use the iptables REDIRECT mechanism to redirect from one port to another inside the kernel (if iptables is not available, then usually ipchains is).
|
||||
|
||||
You need to add something like the following to the startup scripts or
|
||||
your firewall rules:
|
||||
You need to add something like the following to the startup scripts or your firewall rules:
|
||||
|
||||
[source, screen]
|
||||
....
|
||||
----
|
||||
# /sbin/iptables -t nat -I PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080
|
||||
....
|
||||
----
|
||||
|
||||
The underlying model of iptables is different from ipchains, so the
|
||||
forwarding normally happens only to packets originating off-box. You
|
||||
also need to allow incoming packets to port 8080 if you use iptables as
|
||||
a local firewall.
|
||||
The underlying model of iptables is different from ipchains, so the forwarding normally happens only to packets originating off-box.
|
||||
You also need to allow incoming packets to port 8080 if you use iptables as a local firewall.
|
||||
|
||||
Be careful to place rules like this one early in your _input_ chain.
|
||||
Such rules must precede any rule that accepts the packet, otherwise the
|
||||
redirection won't occur. You can insert as many rules as required if
|
||||
your server needs to listen on multiple ports, as for HTTPS.
|
||||
Be careful to place rules like this one early in your _input_ chain.
|
||||
Such rules must precede any rule that accepts the packet, otherwise the redirection won't occur.
|
||||
You can insert as many rules as required if your server needs to listen on multiple ports, as for HTTPS.
|
||||
|
||||
[[configuring-jetty-setuid-feature]]
|
||||
==== Configuring Jetty's SetUID Feature
|
||||
|
||||
http://en.wikipedia.org/wiki/Setuid[SetUID] is a technique that uses
|
||||
Unix-like file system access right to allow users to run an executable
|
||||
that would otherwise require higher privileges.
|
||||
http://en.wikipedia.org/wiki/Setuid[SetUID] is a technique that uses Unix-like file system access right to allow users to run an executable that would otherwise require higher privileges.
|
||||
|
||||
Jetty's SetUID module allows you to run Jetty as a normal user even when
|
||||
you need to run Jetty on port 80 or 443.
|
||||
Jetty's `SetUID` module allows you to run Jetty as a normal user even when you need to run Jetty on port 80 or 443.
|
||||
|
||||
To use it with the jetty distribution:
|
||||
To use it with the Jetty distribution:
|
||||
|
||||
1. Ensure that you have the http.mod (and
|
||||
link:#quickstart-starting-https[https.mod] if you are using SSL)
|
||||
link:#startup-modules[modules enabled] for the
|
||||
link:#creating-jetty-base[base] you are using. The http.mod is enabled
|
||||
by default in the distribution, while the
|
||||
link:#quickstart-starting-https[https.mod] is only enabled in the
|
||||
link:#demo-webapps-base[demo-base] directory.
|
||||
2. Ensure that you have link:#quickstart-changing-jetty-port[changed
|
||||
the http port] to 80 (and link:#quickstart-changing-https-port[changed
|
||||
the https port] to 443 if you are using SSL).
|
||||
3. Enable the setuid.mod module:
|
||||
1. Ensure that you have the `http.mod` (and link:#quickstart-starting-https[https.mod] if you are using SSL) link:#startup-modules[modules enabled] for the link:#creating-jetty-base[base] you are using.
|
||||
The `http.mod` is enabled by default in the distribution, while the link:#quickstart-starting-https[https.mod] is only enabled in the link:#demo-webapps-base[demo-base] directory.
|
||||
2. Ensure that you have link:#quickstart-changing-jetty-port[changed the http port] to 80 (and link:#quickstart-changing-https-port[changed the https port] to 443 if you are using SSL).
|
||||
3. Enable the `setuid.mod` module:
|
||||
+
|
||||
[source, screen]
|
||||
....
|
||||
----
|
||||
# java -jar start.jar --add-to-start=setuid
|
||||
....
|
||||
----
|
||||
+
|
||||
____
|
||||
[NOTE]
|
||||
|
@ -105,9 +79,10 @@ The --add-to-start command will enable the setuid module for this and all subseq
|
|||
There are other ways to enable the module, such as just for this execution.
|
||||
For more information on the alternatives see the section on link:#startup-modules[Managing Startup Modules].
|
||||
____
|
||||
4. Edit the configuration for the setuid module to substitute the userid and groupid of the user to switch to after starting.
|
||||
4. Edit the configuration for the `setuid` module to substitute the `userid` and `groupid` of the user to switch to after starting.
|
||||
If you used the `--add-to-start` command, this configuration is in the `start.ini` file.
|
||||
If you used the `--add-to-startd` command instead, this configuration is in the `start.d/setuid.ini `file instead.
|
||||
|
||||
Here are the lines to configure:
|
||||
+
|
||||
[source,text]
|
||||
|
@ -122,50 +97,38 @@ ____
|
|||
[NOTE]
|
||||
As well as opening the connectors as root, you can also have jetty start the Server as root before changing to the non-root user.
|
||||
____
|
||||
5. You now need a native code library to do the user switching. This
|
||||
code is hosted as part of the Jetty ToolChain project and it is released
|
||||
independently from Jetty itself. You can find the source code
|
||||
https://github.com/eclipsejetty.toolchain[here] in the
|
||||
https://github.com/eclipse/jetty.toolchain/jetty-setuid[jetty-setuid]
|
||||
project. Build it locally, which will produce a native library
|
||||
appropriate for the operating system:
|
||||
|
||||
5. You now need a native code library to do the user switching.
|
||||
This code is hosted as part of the Jetty ToolChain project and it is released independently from Jetty itself.
|
||||
You can find the source code https://github.com/eclipsejetty.toolchain[here] in the https://github.com/eclipse/jetty.toolchain/jetty-setuid[jetty-setuid] project.
|
||||
Build it locally, which will produce a native library appropriate for the operating system:
|
||||
+
|
||||
[source, screen]
|
||||
....
|
||||
----
|
||||
# mvn clean install
|
||||
....
|
||||
----
|
||||
+
|
||||
If you built on a linux machine you will find the native library in
|
||||
`jetty-setuid/libsetuid-linux/target/libsetuid-linux.so`. If you built
|
||||
on a different operating system you will find the library in a different
|
||||
subdirectory, with the name containing the name of the operating system.
|
||||
You might like to copy this file into your jetty distribution's lib
|
||||
directory.
|
||||
6. Start jetty as the root user in your base directory, providing the
|
||||
location of the native library to java. Here's an example of how to do
|
||||
it on the command line, assuming were are in the
|
||||
link:#demo-webapps-base[demo-base] directory:
|
||||
If you built on a linux machine you will find the native library in `jetty-setuid/libsetuid-linux/target/libsetuid-linux.so`.
|
||||
If you built on a different operating system you will find the library in a different subdirectory, with the name containing the name of the operating system.
|
||||
You might like to copy this file into your jetty distribution's lib directory.
|
||||
6. Start jetty as the root user in your base directory, providing the location of the native library to java.
|
||||
Here's an example of how to do it on the command line, assuming were are in the link:#demo-webapps-base[demo-base] directory:
|
||||
+
|
||||
[source, screen]
|
||||
....
|
||||
----
|
||||
# sudo java -Djava.library.path=libsetuid-linux -jar $JETTY_HOME/start.jar
|
||||
....
|
||||
----
|
||||
|
||||
[[using-solaris10-user-rights-management-framework]]
|
||||
==== Using the Solaris 10 User Rights Management Framework
|
||||
|
||||
Solaris 10 provides a User Rights Management framework that can permit
|
||||
users and processes superuser-like abilities:
|
||||
Solaris 10 provides a User Rights Management framework that can permit users and processes superuser-like abilities:
|
||||
|
||||
[source, screen]
|
||||
....
|
||||
----
|
||||
usermod -K defaultpriv=basic,net_privaddr myself
|
||||
....
|
||||
----
|
||||
|
||||
Now the `myself` user can bind to port 80.
|
||||
|
||||
Refer to the
|
||||
http://docs.oracle.com/cd/E23823_01/html/816-4557/prbactm-1.html#scrolltoc[Solaris
|
||||
10] and
|
||||
http://docs.oracle.com/cd/E23824_01/html/821-1456/prbactm-1.html#scrolltoc[Solaris
|
||||
11 Security Services documentation] for more information.
|
||||
Refer to the http://docs.oracle.com/cd/E23823_01/html/816-4557/prbactm-1.html#scrolltoc[Solaris 10] and http://docs.oracle.com/cd/E23824_01/html/821-1456/prbactm-1.html#scrolltoc[Solaris 11 Security Services documentation] for more information.
|
||||
|
|
|
@ -17,33 +17,15 @@
|
|||
[[configuring-virtual-hosts]]
|
||||
=== Configuring Virtual Hosts
|
||||
|
||||
A virtual host is an alternative name, registered in DNS, for an IP
|
||||
address such that multiple domain names will resolve to the same IP of a
|
||||
shared server instance. If the content to be served to the aliases names
|
||||
is link:#different-virtual-hosts-different-contexts[different], then a
|
||||
virtual host needs to be configured for each deployed
|
||||
link:{JDURL}/org/eclipse/jetty/server/handler/ContextHandler.html[context]
|
||||
to indicate which names a context will respond to.
|
||||
A virtual host is an alternative name, registered in DNS, for an IP address such that multiple domain names will resolve to the same IP of a shared server instance.
|
||||
If the content to be served to the aliases names is link:#different-virtual-hosts-different-contexts[different], then a virtual host needs to be configured for each deployed link:{JDURL}/org/eclipse/jetty/server/handler/ContextHandler.html[context] to indicate which names a context will respond to.
|
||||
|
||||
Virtual hosts are set on a
|
||||
link:{JDURL}/org/eclipse/jetty/server/handler/ContextHandler.html[context]
|
||||
by calling the
|
||||
link:{JDURL}/org/eclipse/jetty/server/handler/ContextHandler.html#setVirtualHosts-java.lang.String:A-[`setVirtualHosts`]
|
||||
or
|
||||
link:{JDURL}/org/eclipse/jetty/server/handler/ContextHandler.html#addVirtualHosts-java.lang.String:A-[`addVirtualHost`]
|
||||
method which can be done either
|
||||
Virtual hosts are set on a link:{JDURL}/org/eclipse/jetty/server/handler/ContextHandler.html[context] by calling the link:{JDURL}/org/eclipse/jetty/server/handler/ContextHandler.html#setVirtualHosts-java.lang.String:A-[`setVirtualHosts`] or link:{JDURL}/org/eclipse/jetty/server/handler/ContextHandler.html#addVirtualHosts-java.lang.String:A-[`addVirtualHost`] method which can be done in several ways:
|
||||
|
||||
* Using a link:#deployable-descriptor-file[context XML] file in the
|
||||
webapps directory (see the example in
|
||||
link:{SRCDIR}/tests/test-webapps/test-jetty-webapp/src/main/config/demo-base/webapps/test.xml[test.xml]
|
||||
in the jetty distribution).
|
||||
* Using a link:#deployable-descriptor-file[context XML] file in the webapps directory (see the example in link:{SRCDIR}/tests/test-webapps/test-jetty-webapp/src/main/config/demo-base/webapps/test.xml[test.xml] in the Jetty distribution).
|
||||
* Using a `WEB-INF/jetty-web.xml` file (deprecated).
|
||||
* Creating a link:#deployment-architecture[custom deployer] with a
|
||||
binding to configure virtual hosts for all contexts found in the same
|
||||
webapps directory.
|
||||
* Calling the
|
||||
link:{JDURL}/org/eclipse/jetty/server/handler/ContextHandler.html#setVirtualHosts-java.lang.String:A-[API]
|
||||
directly on an link:#advanced-embedding[embedded] usage.
|
||||
* Creating a link:#deployment-architecture[custom deployer] with a binding to configure virtual hosts for all contexts found in the same `webapps` directory.
|
||||
* Calling the link:{JDURL}/org/eclipse/jetty/server/handler/ContextHandler.html#setVirtualHosts-java.lang.String:A-[API] directly on an link:#advanced-embedding[embedded] usage.
|
||||
|
||||
[[configuring-a-virtual-host]]
|
||||
==== Virtual Host Names
|
||||
|
@ -51,44 +33,23 @@ directly on an link:#advanced-embedding[embedded] usage.
|
|||
Jetty supports the following styles of virtual host name:
|
||||
|
||||
www.hostname.com::
|
||||
A fully qualified host name. It is important to list all variants as a
|
||||
site may receive traffic from both www.hostname.com and just
|
||||
hostname.com
|
||||
A fully qualified host name. It is important to list all variants as a site may receive traffic from both www.hostname.com and just hostname.com
|
||||
*.hostname.com::
|
||||
A wildcard qualified host which will match only one level of arbitrary
|
||||
names. *.foo.com will match www.foo.com and m.foo.com, but not
|
||||
www.other.foo.com
|
||||
A wildcard qualified host which will match only one level of arbitrary names.
|
||||
*.foo.com will match www.foo.com and m.foo.com, but not www.other.foo.com
|
||||
10.0.0.2::
|
||||
An IP address may be given as a virtual host name to indicate that a
|
||||
context should handle requests received on that server port that do
|
||||
not have a host name specified (HTTP/0.9 or HTTP/1.0)
|
||||
An IP address may be given as a virtual host name to indicate that a context should handle requests received on that server port that do not have a host name specified (HTTP/0.9 or HTTP/1.0).
|
||||
@ConnectorName::
|
||||
A connector name, which is not strictly a virtual host, but instead
|
||||
will only match requests that are received on connectors that have a
|
||||
matching name set with
|
||||
link:{JDURL}/org/eclipse/jetty/server/AbstractConnector.html#setName(java.lang.String)[Connector.setName(String)].
|
||||
A connector name, which is not strictly a virtual host, but instead will only match requests that are received on connectors that have a matching name set with link:{JDURL}/org/eclipse/jetty/server/AbstractConnector.html#setName(java.lang.String)[Connector.setName(String)].
|
||||
www.√integral.com::
|
||||
Non ascii and
|
||||
http://en.wikipedia.org/wiki/Internationalized_domain_name[IDN] domain
|
||||
names can be set as virtual hosts using
|
||||
http://en.wikipedia.org/wiki/Punycode[Puny Code] equivalents that may
|
||||
be obtained from a
|
||||
http://network-tools.com/idn-convert.asp[Punycode/IDN converters]. For
|
||||
example if the non ascii domain name `www.√integral.com` is given to a
|
||||
browser, then it will make a request that uses the domain name
|
||||
`www.xn--integral-7g7d.com`, which is the name that should be added as
|
||||
the virtual host name.
|
||||
Non-ASCII and http://en.wikipedia.org/wiki/Internationalized_domain_name[IDN] domain names can be set as virtual hosts using http://en.wikipedia.org/wiki/Punycode[Puny Code] equivalents that may be obtained from a http://network-tools.com/idn-convert.asp[Punycode/IDN converters].
|
||||
For example if the non-ASCII domain name `www.√integral.com` is given to a browser, then it will make a request that uses the domain name `www.xn--integral-7g7d.com`, which is the name that should be added as the virtual host name.
|
||||
|
||||
==== Example Virtual Host Configuration
|
||||
|
||||
Virtual hosts can be used with any context that is a subclass of
|
||||
link:{JDURL}/org/eclipse/jetty/server/handler/ContextHandler.html[ContextHandler].
|
||||
Lets look at an example where we configure a web application -
|
||||
represented by the
|
||||
link:{JDURL}/org/eclipse/jetty/webapp/WebAppContext.html[WebAppContext]
|
||||
class - with virtual hosts. You supply a list of IP addresses and names
|
||||
at which the web application is reachable. Suppose you have a machine
|
||||
with these IP addresses and these DNS resolvable names:
|
||||
Virtual hosts can be used with any context that is a subclass of link:{JDURL}/org/eclipse/jetty/server/handler/ContextHandler.html[ContextHandler].
|
||||
Lets look at an example where we configure a web application -represented by the link:{JDURL}/org/eclipse/jetty/webapp/WebAppContext.html[WebAppContext] class - with virtual hosts.
|
||||
You supply a list of IP addresses and names at which the web application is reachable, such as the following:
|
||||
|
||||
* `333.444.555.666`
|
||||
* `127.0.0.1`
|
||||
|
@ -96,10 +57,8 @@ with these IP addresses and these DNS resolvable names:
|
|||
* `www.blah.net`
|
||||
* `www.blah.org`
|
||||
|
||||
Suppose you have a webapp called `blah.war`, that you want all of the
|
||||
above names and addresses to be served at path "`/blah`". Here's how you
|
||||
would configure the virtual hosts with a
|
||||
link:#deployable-descriptor-file[context XML] file:
|
||||
Suppose you have a webapp called `blah.war`, that you want all of the above names and addresses to be served at path "`/blah`".
|
||||
Here's how you would configure the virtual hosts with a link:#deployable-descriptor-file[context XML] file:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
|
@ -124,8 +83,7 @@ link:#deployable-descriptor-file[context XML] file:
|
|||
[[different-virtual-hosts-different-contexts]]
|
||||
==== Using Different Sets of Virtual Hosts to Select Different Contexts
|
||||
|
||||
You can configure different contexts to respond on different virtual
|
||||
hosts by supplying a specific list of virtual hosts for each one.
|
||||
You can configure different contexts to respond on different virtual hosts by supplying a specific list of virtual hosts for each one.
|
||||
|
||||
For example, suppose your imaginary machine has these DNS names:
|
||||
|
||||
|
@ -134,14 +92,11 @@ For example, suppose your imaginary machine has these DNS names:
|
|||
* `www.blah.org`
|
||||
* `www.other.com`
|
||||
* `www.other.net`
|
||||
* `www.other.org `
|
||||
* `www.other.org`
|
||||
|
||||
Suppose also you have 2 webapps, one called `blah.war` that you would
|
||||
like served from the `*.blah.*` names, and one called `other.war` that
|
||||
you want served only from the `*.other.*` names.
|
||||
Suppose also you have 2 webapps, one called `blah.war` that you would like served from the `*.blah.*` names, and one called `other.war` that you want served only from the `*.other.*` names.
|
||||
|
||||
Using the method of preparing link:#deployable-descriptor-files[context
|
||||
XML] files, one for each webapp yields the following:
|
||||
Using the method of preparing link:#deployable-descriptor-files[contextXML] files, one for each webapp yields the following:
|
||||
|
||||
For `blah` webapp:
|
||||
|
||||
|
@ -163,7 +118,7 @@ For `blah` webapp:
|
|||
</Configure>
|
||||
----
|
||||
|
||||
These urls now resolve to the blah context (ie `blah.war`):
|
||||
These URLs now resolve to the blah context (ie `blah.war`):
|
||||
|
||||
* `http://www.blah.com/blah`
|
||||
* `http://www.blah.net/blah`
|
||||
|
@ -189,7 +144,7 @@ For `other` webapp:
|
|||
</Configure>
|
||||
----
|
||||
|
||||
These urls now resolve to the other context (ie other.war):
|
||||
These URLs now resolve to the other context (i.e. `other.war`):
|
||||
|
||||
* `http://www.other.com/other`
|
||||
* `http://www.other.net/other`
|
||||
|
@ -198,34 +153,25 @@ These urls now resolve to the other context (ie other.war):
|
|||
[[different-virtual-hosts-different-context-same-path]]
|
||||
==== Using Different Sets of Virtual Hosts to Select Different Contexts at the Same Context Path
|
||||
|
||||
In the previous section we setup 2 different contexts to be served from
|
||||
different virtual hosts at _different_ context paths. However, there is
|
||||
no requirement that the context paths must be distinct: you may use the
|
||||
same context path for multiple contexts, and use virtual hosts to
|
||||
determine which one is served for a given request.
|
||||
In the previous section we setup 2 different contexts to be served from different virtual hosts at _different_ context paths.
|
||||
However, there is no requirement that the context paths must be distinct: you may use the same context path for multiple contexts, and use virtual hosts to determine which one is served for a given request.
|
||||
|
||||
Consider an example where we have the same set of DNS names as before,
|
||||
and the same webapps `blah.war` and `other.war`. We still want
|
||||
`blah.war` to be served in response to hostnames of `*.blah.*`, and we
|
||||
still want `other.war` to be served in response to `*.other.*` names.
|
||||
However, we would like__all__ of our clients to use the `"/"` context
|
||||
path, no matter which context is being targeted.
|
||||
Consider an example where we have the same set of DNS names as before, and the same webapps `blah.war` and `other.war`. We still want `blah.war` to be served in response to hostnames of `*.blah.*`, and we still want `other.war` to be served in response to `*.other.*` names.
|
||||
However, we would like__all__ of our clients to use the `"/"` context path, no matter which context is being targeted.
|
||||
|
||||
In other words, we want all of the following urls to map to `blah.war`:
|
||||
In other words, we want all of the following URLs to map to `blah.war`:
|
||||
|
||||
* `http://www.blah.com/`
|
||||
* `http://www.blah.net/`
|
||||
* `http://www.blah.org/`
|
||||
|
||||
Similarly, we want the following urls to map to `other.war`:
|
||||
Similarly, we want the following URLs to map to `other.war`:
|
||||
|
||||
* `http://www.other.com/`
|
||||
* `http://www.other.net/`
|
||||
* `http://www.other.org/`
|
||||
|
||||
To achieve this, we simply use the same context path of "/" for each of
|
||||
our webapps, whilst still applying our different set of virtual host
|
||||
names.
|
||||
To achieve this, we simply use the same context path of `/` for each of our webapps, while still applying our different set of virtual host names.
|
||||
|
||||
For foo webapp:
|
||||
|
||||
|
|
|
@ -17,21 +17,16 @@
|
|||
[[custom-error-pages]]
|
||||
=== Creating Custom Error Pages
|
||||
|
||||
The following sections describe several ways to create custom error
|
||||
pages in Jetty.
|
||||
The following sections describe several ways to create custom error pages in Jetty.
|
||||
|
||||
==== Defining error pages in web.xml
|
||||
|
||||
You can use the standard webapp configuration file located in
|
||||
`webapp/WEB-INF/web.xml` to map errors to specific URLs with the
|
||||
error-page element. This element creates a mapping between the
|
||||
error-code or exception-type to the location of a resource in the web
|
||||
application.
|
||||
You can use the standard webapp configuration file located in `webapp/WEB-INF/web.xml` to map errors to specific URLs with the `error-page` element.
|
||||
This element creates a mapping between the error-code or exception-type to the location of a resource in the web application.
|
||||
|
||||
* error-code - an integer value
|
||||
* exception-type - a fully qualified class name of a Java Exception type
|
||||
* location - location of the resource in the webapp relative to the root
|
||||
of the web application. Value should start with "/".
|
||||
* `error-code` - an integer value
|
||||
* `exception-type` - a fully qualified class name of a Java Exception type
|
||||
* `location` - location of the resource in the webapp relative to the root of the web application. Value should start with `/`.
|
||||
|
||||
Error code example:
|
||||
|
||||
|
@ -55,36 +50,27 @@ Exception example:
|
|||
|
||||
----
|
||||
|
||||
The error page mappings created with the error-page element will
|
||||
redirect to a normal URL within the web application and will be handled
|
||||
as a normal request to that location and thus may be static content, a
|
||||
JSP or a filter and/or servlet. When handling a request generated by an
|
||||
error redirection, the following request attributes are set and are
|
||||
available to generate dynamic content:
|
||||
The error page mappings created with the error-page element will redirect to a normal URL within the web application and will be handled as a normal request to that location and thus may be static content, a JSP or a filter and/or servlet.
|
||||
When handling a request generated by an error redirection, the following request attributes are set and are available to generate dynamic content:
|
||||
|
||||
javax.servlet.error.exception::
|
||||
The exception instance that caused the error (or null)
|
||||
The exception instance that caused the error (or null).
|
||||
javax.servlet.error.exception_type::
|
||||
The class name of the exception instance that caused the error (or
|
||||
null)
|
||||
The class name of the exception instance that caused the error (or null).
|
||||
javax.servlet.error.message::
|
||||
The error message.
|
||||
javax.servlet.error.request_uri::
|
||||
The URI of the errored request.
|
||||
The URI of the request with an error.
|
||||
javax.servlet.error.servlet_name::
|
||||
The Servlet name of the servlet that the errored request was
|
||||
dispatched to/
|
||||
The Servlet name of the servlet that the request was
|
||||
dispatched to.
|
||||
javax.servlet.error.status_code::
|
||||
The status code of the error (e.g. 404, 500 etc.)
|
||||
The status code of the error (e.g. 404, 500 etc.).
|
||||
|
||||
==== Configuring error pages context files
|
||||
|
||||
You can use context IoC XML files to configure the default error page
|
||||
mappings with more flexibility than is available with `web.xml`,
|
||||
specifically with the support of error code ranges. Context files are
|
||||
normally located in `${jetty.home}/webapps/` (see DeployerManager for
|
||||
more details) and an example of more flexible error page mapping is
|
||||
below:
|
||||
You can use context IoC XML files to configure the default error page mappings with more flexibility than is available with `web.xml`, specifically with the support of error code ranges.
|
||||
Context files are normally located in `${jetty.home}/webapps/` (see `DeployerManager` for more details) and an example of more flexible error page mapping is below:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
|
@ -131,12 +117,8 @@ below:
|
|||
|
||||
==== Custom ErrorHandler class
|
||||
|
||||
If no error page mapping is defined, or if the error page resource
|
||||
itself has an error, then the error page will be generated by an
|
||||
instance of ErrorHandler configured either the Context or the Server. An
|
||||
ErrorHandler may extend the ErrorHandler class and may totally replace
|
||||
the handle method to generate an error page, or it can implement some or
|
||||
all of the following methods to partially modify the error pages:
|
||||
If no error page mapping is defined, or if the error page resource itself has an error, then the error page will be generated by an instance of `ErrorHandler` configured either the Context or the Server.
|
||||
An `ErrorHandler` may extend the `ErrorHandler` class and may totally replace the handle method to generate an error page, or it can implement some or all of the following methods to partially modify the error pages:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
|
@ -147,56 +129,43 @@ void writeErrorPageHead(HttpServletRequest request, Writer writer, int code, Str
|
|||
void writeErrorPageBody(HttpServletRequest request, Writer writer, int code, String message, boolean showStacks) throws IOException
|
||||
void writeErrorPageMessage(HttpServletRequest request, Writer writer, int code, String message, String uri) throws IOException
|
||||
void writeErrorPageStacks(HttpServletRequest request, Writer writer) throws IOException
|
||||
|
||||
----
|
||||
|
||||
An ErrorHandler instance may be set on a Context by calling the
|
||||
ContextHandler.setErrorHandler method. This can be done by embedded code
|
||||
or via context IoC XML. For example:
|
||||
An `ErrorHandler` instance may be set on a Context by calling the `ContextHandler.setErrorHandler` method. This can be done by embedded code or via context IoC XML.
|
||||
For example:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<Configure class="org.eclipse.jetty.server.handler.ContextHandler">
|
||||
...
|
||||
|
||||
<Set name="errorHandler">
|
||||
<New class="com.acme.handler.MyErrorHandler"/>
|
||||
</Set>
|
||||
...
|
||||
|
||||
</Configure>
|
||||
|
||||
----
|
||||
|
||||
An ErrorHandler instance may be set on the entire server by setting it
|
||||
as a dependent bean on the Server instance. This can be done by calling
|
||||
Server.addBean(Object) via embedded code or in jetty.xml IoC XML like:
|
||||
An `ErrorHandler` instance may be set on the entire server by setting it as a dependent bean on the Server instance.
|
||||
This can be done by calling `Server.addBean(Object)` via embedded code or in `jetty.xml` IoC XML like:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<Configure id="Server" class="org.eclipse.jetty.server.Server">
|
||||
...
|
||||
|
||||
<Call name="addBean">
|
||||
<Arg>
|
||||
<New class="com.acme.handler.MyErrorHandler"/>
|
||||
</Arg>
|
||||
</Call>
|
||||
...
|
||||
|
||||
</Configure>
|
||||
|
||||
----
|
||||
|
||||
==== Server level 404 error
|
||||
|
||||
You might get a 'page not found' when a request is made to the server
|
||||
for a resource that is outside of any registered contexts. As an
|
||||
example, you have a domain name pointing to your public server IP, yet
|
||||
no context is registered with jetty to serve pages for that domain. As a
|
||||
consequence, the server, by default, gives a listing of all contexts
|
||||
running on the server.
|
||||
It is possible to get a 'page not found' when a request is made to the server for a resource that is outside of any registered contexts.
|
||||
As an example, you have a domain name pointing to your public server IP, yet no context is registered with Jetty to serve pages for that domain.
|
||||
As a consequence, the server, by default, gives a listing of all contexts running on the server.
|
||||
|
||||
One of the quickest ways to avoid this behavior is to create a catch all
|
||||
context. Create a "root" web app mapped to the "/" URI. Have the
|
||||
index.html redirect to whatever place with a header directive.
|
||||
One of the quickest ways to avoid this behavior is to create a catch all context.
|
||||
Create a "root" web app mapped to the "/" URI, and use the `index.html` redirect to whatever place with a header directive.
|
||||
|
|
|
@ -17,65 +17,44 @@
|
|||
[[serving-webapp-from-particular-port]]
|
||||
=== Serving a WebApp from a Particular Port/Connector
|
||||
|
||||
Sometimes it is required to serve different web applications from
|
||||
different ports/connectors. The simplest way to do this is to create
|
||||
multiple `Server` instances, however if contexts need to share resources
|
||||
(eg data sources, authentication), or if the mapping of ports to web
|
||||
applications is not cleanly divided, then the named connector mechanism
|
||||
can be used.
|
||||
Sometimes it is required to serve different web applications from different ports/connectors.
|
||||
The simplest way to do this is to create multiple `Server` instances.
|
||||
However, if contexts need to share resources (eg data sources, authentication), or if the mapping of ports to web applications is not cleanly divided, then the named connector mechanism can be used.
|
||||
|
||||
[[creating-server-instances]]
|
||||
==== Creating Multiple Server Instances
|
||||
|
||||
How to create multiple server instances is simply done when writing
|
||||
embedded jetty code by creating multiples instances of the Server class
|
||||
and configuring them as needed. This is also easy to achieve if you are
|
||||
configuring your servers in XML. The id field in the Configure element
|
||||
of jetty.xml files is used to identify the instance that the
|
||||
configuration applies to, so to run two instances of the Server, you can
|
||||
copy the jetty.xml, jetty-http.xml and other jetty configuration files
|
||||
used and change the "Server" id to a new name. This can be done in the
|
||||
same style and layout as the existing jetty.xml files or the multiple
|
||||
XML files may be combined to a single file.
|
||||
Creating multiple server instances is a straight forward process that includes embedding Jetty code by creating multiples instances of the Server class and configuring them as needed.
|
||||
This is also easy to achieve if you are configuring your servers in XML.
|
||||
The `id` field in the Configure element of `jetty.xml` files is used to identify the instance that the configuration applies to, so to run two instances of the Server, you can copy the `jetty.xml`, jetty-http.xml and other jetty configuration files used and change the "Server" id to a new name.
|
||||
This can be done in the same style and layout as the existing `jetty.xml` files or the multiple XML files may be combined to a single file.
|
||||
|
||||
When creating new configurations for alternative server:
|
||||
|
||||
* Change all id="Server" to the new server
|
||||
name:`<Configure id="OtherServer"
|
||||
class="org.eclipse.jetty.server.Server"> `
|
||||
* For all connectors for the new server change the refid in the server
|
||||
argument: `<Arg name="server"><Ref
|
||||
refid="OtherServer" /></Arg>`
|
||||
* Make sure that any references to properties like jetty.http.port are
|
||||
either renamed or replaced with absolute values
|
||||
* Make sure that any deployers AppProviders refer to a different
|
||||
"webapps" directory so that a different set of applications are
|
||||
deployed.
|
||||
* Change all `id="Server"` to the new server name: `<Configure id="OtherServer" class="org.eclipse.jetty.server.Server">`
|
||||
* For all connectors for the new server change the `refid` in the server argument: `<Arg name="server"><Ref refid="OtherServer" /></Arg>`
|
||||
* Make sure that any references to properties like `jetty.http.port` are either renamed or replaced with absolute values
|
||||
* Make sure that any deployers `AppProviders` refer to a different "webapps" directory so that a different set of applications are deployed.
|
||||
|
||||
[[jetty-otherserver.xml]]
|
||||
===== Example Other Server XML
|
||||
|
||||
The following example creates another server instance and configures it
|
||||
with a connector and deployer:
|
||||
The following example creates another server instance and configures it with a connector and deployer:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
include::{SRCDIR}/examples/embedded/src/main/resources/jetty-otherserver.xml[]
|
||||
----
|
||||
|
||||
To run the other server, simply add the extra configuration file(s) to
|
||||
the command line:
|
||||
To run the other server, add the extra configuration file(s) to the command line:
|
||||
|
||||
[source, screen]
|
||||
....
|
||||
----
|
||||
java -jar start.jar jetty-otherserver.xml
|
||||
....
|
||||
----
|
||||
|
||||
[[alternative]]
|
||||
==== Named Connectors
|
||||
|
||||
It is also possible to use an extension to the virtual host mechanism
|
||||
with named to connectors to make some web applications only accessible
|
||||
by specific connectors. If a connector has a name "MyConnector" set
|
||||
using the setName method, then this can be referenced with the special
|
||||
virtual host name "@MyConnector".
|
||||
It is also possible to use an extension to the virtual host mechanism with named to connectors to make some web applications only accessible by specific connectors.
|
||||
If a connector has a name "MyConnector" set using the `setName` method, then this can be referenced with the special virtual host name "@MyConnector".
|
||||
|
|
|
@ -17,63 +17,42 @@
|
|||
[[setting-context-path]]
|
||||
=== Setting a Context Path
|
||||
|
||||
The context path is the prefix of a URL path that is used to select the
|
||||
context(s) to which an incoming request is passed. Typically a URL in a
|
||||
Java servlet server is of the format `
|
||||
http://hostname.com/contextPath/servletPath/pathInfo`, where each of
|
||||
the path elements can be zero or more / separated elements. If there is
|
||||
no context path, the context is referred to as the _root_ context. The
|
||||
root context must be configured as "/" but is reported as the empty
|
||||
string by the servlet API getContextPath() method.
|
||||
The context path is the prefix of a URL path that is used to select the context(s) to which an incoming request is passed. Typically a URL in a Java servlet server is of the format `http://hostname.com/contextPath/servletPath/pathInfo`, where each of the path elements can be zero or more / separated elements.
|
||||
If there is no context path, the context is referred to as the _root_ context.
|
||||
The root context must be configured as `/` but is reported as the empty string by the servlet API `getContextPath()` method.
|
||||
|
||||
How you set the context path depends on how you deploy the web
|
||||
application (or ContextHandler):
|
||||
How you set the context path depends on how you deploy the web application (or `ContextHandler`).
|
||||
|
||||
[[using-embedded-deployment]]
|
||||
==== Using Embedded Deployment
|
||||
|
||||
If you run Jetty from code as an embedded server (see
|
||||
link:#advanced-embedding[Embedding]), setting the context path is a
|
||||
matter of calling the `setContextPath` method on the `ContextHandler`
|
||||
instance (or `WebAppContext` instance).
|
||||
If you run Jetty from code as an embedded server (see link:#advanced-embedding[Embedding]), setting the context path is a matter of calling the `setContextPath` method on the `ContextHandler` instance (or `WebAppContext` instance).
|
||||
|
||||
[[usng-the-context-provider]]
|
||||
==== By naming convention
|
||||
|
||||
If a web application is deployed using the WebAppProvider of the
|
||||
DeploymentManager without an XML IoC file, then the name of the WAR file
|
||||
is used to set the context path:
|
||||
If a web application is deployed using the WebAppProvider of the DeploymentManager without an XML IoC file, then the name of the WAR file is used to set the context path:
|
||||
|
||||
* If the WAR file is named myapp.war, then the context will be deployed
|
||||
with a context path of /myapp
|
||||
* If the WAR file is named ROOT.WAR (or any case insensitive variation),
|
||||
then the context will be deployed with a context path of /
|
||||
* If the WAR file is named ROOT-foobar.war ( or any case insensitive
|
||||
variation), then the context will be deployed with a context path of /
|
||||
and a virtual host of "foobar"
|
||||
* If the WAR file is named myapp.war, then the context will be deployed with a context path of `/myapp`
|
||||
* If the WAR file is named ROOT.WAR (or any case insensitive variation), then the context will be deployed with a context path of `/`
|
||||
* If the WAR file is named ROOT-foobar.war ( or any case insensitive variation), then the context will be deployed with a context path of `/` and a virtual host of "foobar"
|
||||
|
||||
[[using-the-webapp-provider]]
|
||||
==== By Deployer configuration
|
||||
|
||||
If a web application is deployed using the WebAppProvider of the
|
||||
DeploymentManager with an XML IoC file to configure the context, then
|
||||
the setContextPath method can be called within that file. For example:
|
||||
If a web application is deployed using the `WebAppProvider` of the `DeploymentManager` with an XML IoC file to configure the context, then the `setContextPath` method can be called within that file.
|
||||
For example:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
|
||||
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
|
||||
<Set name="contextPath">/test</Set>
|
||||
...
|
||||
</Configure>
|
||||
|
||||
|
||||
----
|
||||
|
||||
[[embedding-web-inf-jetty-web.xml-file]]
|
||||
==== Embedding a WEB-INF/jetty-web.xml File
|
||||
|
||||
You can also set the context path for webapps by embedding a
|
||||
`WEB-INF/jetty-web.xml` file in the WAR, which uses the same XML IoC
|
||||
format as the deployer example above. However this is not the preferred
|
||||
method as it requires the web application to be modified.
|
||||
You can also set the context path for webapps by embedding a `WEB-INF/jetty-web.xml` file in the WAR, which uses the same XML IoC format as the deployer example above.
|
||||
However this is not the preferred method as it requires the web application to be modified.
|
||||
|
|
|
@ -17,58 +17,44 @@
|
|||
[[setting-form-size]]
|
||||
=== Setting Max Form Size
|
||||
|
||||
Jetty limits the amount of data that can post back from a browser or
|
||||
other client to the server. This helps protect the server against denial
|
||||
of service attacks by malicious clients sending huge amounts of data.
|
||||
The default maximum size Jetty permits is 200000 bytes. You can change
|
||||
this default for a particular webapp, for all webapps on a particular
|
||||
Server instance, or all webapps within the same JVM.
|
||||
Jetty limits the amount of data that can post back from a browser or other client to the server.
|
||||
This helps protect the server against denial of service attacks by malicious clients sending huge amounts of data.
|
||||
The default maximum size Jetty permits is 200000 bytes.
|
||||
You can change this default for a particular webapp, for all webapps on a particular Server instance, or all webapps within the same JVM.
|
||||
|
||||
==== For a Single Webapp
|
||||
|
||||
The method to invoke is:
|
||||
`ContextHandler.setMaxFormContentSize(int maxSize);`
|
||||
The method to invoke is: `ContextHandler.setMaxFormContentSize(int maxSize);`
|
||||
|
||||
You can do this either in a context XML deployment descriptor external
|
||||
to the webapp, or in a `jetty-web.xml` file in the webapp's WEB-INF
|
||||
directory.
|
||||
This can be done either in a context XML deployment descriptor external to the webapp, or in a `jetty-web.xml` file in the webapp's `WEB-INF` directory.
|
||||
|
||||
In either case the syntax of the XML file is the same:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
|
||||
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
|
||||
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
|
||||
<!-- Max Form Size -->
|
||||
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
|
||||
<Set name="maxFormContentSize">200000</Set>
|
||||
</Configure>
|
||||
|
||||
|
||||
----
|
||||
|
||||
==== For All Apps on a Server
|
||||
|
||||
Set an attribute on the Server instance for which you want to modify the
|
||||
maximum form content size:
|
||||
Set an attribute on the Server instance for which you want to modify the maximum form content size:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
|
||||
<Configure class="org.eclipse.jetty.server.Server">
|
||||
<Call name="setAttribute">
|
||||
<Arg>org.eclipse.jetty.server.Request.maxFormContentSize</Arg>
|
||||
<Arg>200000</Arg>
|
||||
</Call>
|
||||
</Configure>
|
||||
|
||||
|
||||
----
|
||||
|
||||
==== For All Apps in the JVM
|
||||
|
||||
Use the system property
|
||||
`org.eclipse.jetty.server.Request.maxFormContentSize`. This can be set
|
||||
on the commandline or in the start.ini file.
|
||||
|
||||
Use the system property `org.eclipse.jetty.server.Request.maxFormContentSize`.
|
||||
This can be set on the command line or in the `start.ini` file.
|
||||
|
|
|
@ -17,18 +17,13 @@
|
|||
[[ref-temporary-directories]]
|
||||
=== Temporary Directories
|
||||
|
||||
Jetty itself has no temporary directories, but you can assign a
|
||||
directory for each web application, into which the WAR is unpacked, JSPs
|
||||
compiled on-the-fly, etc. If you do not assign a specific temporary
|
||||
directory, Jetty will create one as needed when your web application
|
||||
starts. Whether you set the location of the temporary directory - or you
|
||||
let Jetty create one for you - you also have a choice to either keep or
|
||||
delete the temporary directory when the web application stops.
|
||||
Jetty itself has no temporary directories, but you can assign a directory for each web application, into which the WAR is unpacked, JSPs compiled on-the-fly, etc.
|
||||
If you do not assign a specific temporary directory, Jetty will create one as needed when your web application starts.
|
||||
Whether you set the location of the temporary directory - or you let Jetty create one for you - you also have a choice to either keep or delete the temporary directory when the web application stops.
|
||||
|
||||
==== The default temp directory
|
||||
|
||||
By default, Jetty will create a temporary directory for each web
|
||||
application. The name of the directory will be of the form:
|
||||
By default, Jetty will create a temporary directory for each web application. The name of the directory will be of the form:
|
||||
|
||||
....
|
||||
"jetty-"+host+"-"+port+"-"+resourceBase+"-_"+context+"-"+virtualhost+"-"+randomdigits+".dir"
|
||||
|
@ -40,26 +35,19 @@ For example:
|
|||
jetty-0.0.0.0-8080-test.war-_test-any-8900275691885214790.dir
|
||||
....
|
||||
|
||||
Where `0.0.0.0` is the host address, `8080` is the port, `test.war` is
|
||||
the resourceBase, `test` is the context path (with / converted to _),
|
||||
`any` is the virtual host, and `randomdigits` are a string of digits
|
||||
guaranteed to be unique.
|
||||
Where `0.0.0.0` is the host address, `8080` is the port, `test.war` is the resourceBase, `test` is the context path (with / converted to _), `any` is the virtual host, and `randomdigits` are a string of digits guaranteed to be unique.
|
||||
|
||||
Once the temp directory is created, it is retrievable as the value (as a
|
||||
File) of the context attribute `javax.servlet.context.tempdir.`
|
||||
Once the temp directory is created, it is retrievable as the value (as a File) of the context attribute `javax.servlet.context.tempdir.`
|
||||
|
||||
===== The location of the temp directory
|
||||
|
||||
By default, jetty will create this directory inside the directory named
|
||||
by the `java.io.tmpdir` System property. You can instruct Jetty to use a
|
||||
different parent directory by setting the context attribute
|
||||
`org.eclipse.jetty.webapp.basetempdir` to the name of the desired parent
|
||||
directory. The directory named by this attribute _must_ exist and be
|
||||
__writeable__.
|
||||
By default, Jetty will create this directory inside the directory named by the `java.io.tmpdir` System property.
|
||||
You can instruct Jetty to use a different parent directory by setting the context attribute `org.eclipse.jetty.webapp.basetempdir` to the name of the desired parent directory.
|
||||
The directory named by this attribute _must_ exist and be __writeable__.
|
||||
|
||||
As usual with Jetty, you can either set this attribute in a context xml
|
||||
file, or you can do it in code. Here's an example of setting it in an
|
||||
xml file:
|
||||
As usual with Jetty, you can either set this attribute in a context xml file, or you can do it in code.
|
||||
|
||||
Here's an example of setting it in an xml file:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
|
@ -87,12 +75,10 @@ context.setAttribute("org.eclipse.jetty.webapp.basetempdir", "/tmp/foo");
|
|||
|
||||
==== Setting a specific temp directory
|
||||
|
||||
To use a particular directory as the temporary directory you can do
|
||||
either:
|
||||
There are several ways to use a particular directory as the temporary directory:
|
||||
|
||||
call WebAppContext.setTempDirectory(String dir)::
|
||||
As usual with Jetty, you can do this with an xml file or directly in
|
||||
code. Here's an example of setting the temp directory in xml:
|
||||
Like before this can be accomplished with an xml file or directly in code. Here's an example of setting the temp directory in xml:
|
||||
+
|
||||
[source,xml]
|
||||
----
|
||||
|
@ -116,8 +102,7 @@ context.setTempDirectory(new File("/some/dir/foo"));
|
|||
----
|
||||
|
||||
set the `javax.servlet.context.tempdir` context attribute::
|
||||
You should set this context attribute with the name of directory you
|
||||
want to use as the temp directory. Again, you can do this in xml:
|
||||
You should set this context attribute with the name of directory you want to use as the temp directory. Again, you can do this in xml:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
|
@ -144,9 +129,7 @@ context.setWar("foo.war");
|
|||
context.setAttribute("javax.servlet.context.tempdir", "/some/dir/foo");
|
||||
----
|
||||
|
||||
Once a temporary directory has been created by either of these methods,
|
||||
a File instance for it is set as the value of the
|
||||
`javax.servlet.context.tempdir` attribute of the web application.
|
||||
Once a temporary directory has been created by either of these methods, a File instance for it is set as the value of the `javax.servlet.context.tempdir` attribute of the web application.
|
||||
|
||||
____
|
||||
[NOTE]
|
||||
|
@ -156,27 +139,20 @@ ____
|
|||
|
||||
==== The "work" directory
|
||||
|
||||
Mostly for backward compatibility, from jetty-9.1.1 onwards, it will be
|
||||
possible to create a directory named "work" in the $\{jetty.base}
|
||||
directory. If such a directory is found, it is assumed you want to use
|
||||
it as the parent directory for all of the temporary directories of the
|
||||
webapps in that $\{jetty.base}. Moreover, as has historically been the
|
||||
case, these temp directories inside the work directory are not cleaned
|
||||
up when jetty exists (or more correctly speaking, the temp dir
|
||||
corresponding to a context is not cleaned up when that context stops).
|
||||
Mostly for backward compatibility, from jetty-9.1.1 onwards, it is be possible to create a directory named "work" in the `$\{jetty.base}` directory.
|
||||
If such a directory is found, it is assumed you want to use it as the parent directory for all of the temporary directories of the webapps in that `$\{jetty.base}`.
|
||||
Moreover, as has historically been the case, these temp directories inside the work directory are not cleaned up when jetty exists (or more correctly speaking, the `temp` directory corresponding to a context is not cleaned up when that context stops).
|
||||
|
||||
When a work directory is used, the algorithm for generating the name of
|
||||
the context-specific temp dirs omits the random digit string. This
|
||||
ensures the name of the dir remains consistent across context restarts.
|
||||
When a work directory is used, the algorithm for generating the name of the context-specific temp directories omits the random digit string.
|
||||
This ensures the name of the directory remains consistent across context restarts.
|
||||
|
||||
==== Persisting the temp directory
|
||||
|
||||
Sometimes you may find it useful to keep the contents of the temporary
|
||||
directory between restarts of the web application. By default, Jetty
|
||||
will _not_ persist the temp directory. To cause Jetty to keep it, use
|
||||
link:{JDURL}/org/eclipse/jetty/webapp/WebAppContext.html[WebAppContext.setPersistTempDirectory(true)].
|
||||
Sometimes you may find it useful to keep the contents of the temporary directory between restarts of the web application.
|
||||
By default, Jetty will _not_ persist the temp directory.
|
||||
To configure Jetty to keep it, use link:{JDURL}/org/eclipse/jetty/webapp/WebAppContext.html[WebAppContext.setPersistTempDirectory(true)].
|
||||
|
||||
Be aware that if you call setPersistTempDirectory(true), but let Jetty
|
||||
create a new temp directory each time (ie you do NOT set an explicit
|
||||
temp directory), then you will accumulate temp directories in your
|
||||
chosen temp directory location.
|
||||
____
|
||||
[NOTE]
|
||||
Be aware that if you call `setPersistTempDirectory(true)`, but let Jetty create a new temp directory each time (i.e. you do NOT set an explicit temp directory), then you will accumulate temp directories in your chosen temp directory location.
|
||||
____
|
||||
|
|
|
@ -94,14 +94,10 @@ public class ALPNNegotiationTest extends AbstractALPNTest
|
|||
// Now if we read more, we should read a TLS Alert.
|
||||
encrypted.clear();
|
||||
read = channel.read(encrypted);
|
||||
if (read > 0)
|
||||
{
|
||||
encrypted.flip();
|
||||
// TLS Alert message type == 21.
|
||||
Assert.assertEquals(21, encrypted.get() & 0xFF);
|
||||
encrypted.clear();
|
||||
Assert.assertEquals(-1, channel.read(encrypted));
|
||||
}
|
||||
Assert.assertTrue(read > 0);
|
||||
Assert.assertEquals(21, encrypted.get(0));
|
||||
encrypted.clear();
|
||||
Assert.assertEquals(-1, channel.read(encrypted));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -151,11 +147,12 @@ public class ALPNNegotiationTest extends AbstractALPNTest
|
|||
ByteBuffer decrypted = ByteBuffer.allocate(sslEngine.getSession().getApplicationBufferSize());
|
||||
sslEngine.unwrap(encrypted, decrypted);
|
||||
|
||||
// Now if we read more, we should either read the TLS Close Alert, or directly -1
|
||||
// Now if we read more, we should read the TLS Close Alert.
|
||||
encrypted.clear();
|
||||
read = channel.read(encrypted);
|
||||
// Since we have close the connection abruptly, the server also does so
|
||||
Assert.assertTrue(read < 0);
|
||||
encrypted.flip();
|
||||
Assert.assertTrue(read > 0);
|
||||
Assert.assertEquals(21, encrypted.get(0));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -81,7 +81,7 @@ public abstract class AbstractEndPoint extends IdleTimeout implements EndPoint
|
|||
// If somebody else switched to CLOSED while we were ishutting,
|
||||
// then we do the close for them
|
||||
if (_state.get()==State.CLOSED)
|
||||
doOnClose();
|
||||
doOnClose(null);
|
||||
else
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
@ -102,7 +102,7 @@ public abstract class AbstractEndPoint extends IdleTimeout implements EndPoint
|
|||
if (!_state.compareAndSet(s,State.CLOSED))
|
||||
continue;
|
||||
// Already OSHUT so we close
|
||||
doOnClose();
|
||||
doOnClose(null);
|
||||
return;
|
||||
|
||||
case CLOSED: // already closed
|
||||
|
@ -133,7 +133,7 @@ public abstract class AbstractEndPoint extends IdleTimeout implements EndPoint
|
|||
// If somebody else switched to CLOSED while we were oshutting,
|
||||
// then we do the close for them
|
||||
if (_state.get()==State.CLOSED)
|
||||
doOnClose();
|
||||
doOnClose(null);
|
||||
else
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
@ -150,7 +150,7 @@ public abstract class AbstractEndPoint extends IdleTimeout implements EndPoint
|
|||
if (!_state.compareAndSet(s,State.CLOSED))
|
||||
continue;
|
||||
// Already ISHUT so we close
|
||||
doOnClose();
|
||||
doOnClose(null);
|
||||
return;
|
||||
|
||||
case OSHUTTING: // Somebody else oshutting
|
||||
|
@ -165,6 +165,11 @@ public abstract class AbstractEndPoint extends IdleTimeout implements EndPoint
|
|||
|
||||
@Override
|
||||
public final void close()
|
||||
{
|
||||
close(null);
|
||||
}
|
||||
|
||||
protected final void close(Throwable failure)
|
||||
{
|
||||
while(true)
|
||||
{
|
||||
|
@ -176,7 +181,7 @@ public abstract class AbstractEndPoint extends IdleTimeout implements EndPoint
|
|||
case OSHUT: // Already oshut
|
||||
if (!_state.compareAndSet(s,State.CLOSED))
|
||||
continue;
|
||||
doOnClose();
|
||||
doOnClose(failure);
|
||||
return;
|
||||
|
||||
case ISHUTTING: // Somebody else ishutting
|
||||
|
@ -193,15 +198,14 @@ public abstract class AbstractEndPoint extends IdleTimeout implements EndPoint
|
|||
}
|
||||
|
||||
protected void doShutdownInput()
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
protected void doShutdownOutput()
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
protected void doClose()
|
||||
{}
|
||||
|
||||
private void doOnClose()
|
||||
private void doOnClose(Throwable failure)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -209,10 +213,24 @@ public abstract class AbstractEndPoint extends IdleTimeout implements EndPoint
|
|||
}
|
||||
finally
|
||||
{
|
||||
onClose();
|
||||
if (failure == null)
|
||||
onClose();
|
||||
else
|
||||
onClose(failure);
|
||||
}
|
||||
}
|
||||
|
||||
protected void doClose()
|
||||
{
|
||||
}
|
||||
|
||||
protected void onClose(Throwable failure)
|
||||
{
|
||||
super.onClose();
|
||||
_writeFlusher.onFail(failure);
|
||||
_fillInterest.onFail(failure);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOutputShutdown()
|
||||
{
|
||||
|
@ -324,8 +342,6 @@ public abstract class AbstractEndPoint extends IdleTimeout implements EndPoint
|
|||
public void onClose()
|
||||
{
|
||||
super.onClose();
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("onClose {}",this);
|
||||
_writeFlusher.onClose();
|
||||
_fillInterest.onClose();
|
||||
}
|
||||
|
|
|
@ -268,7 +268,7 @@ abstract public class WriteFlusher
|
|||
if (_callback!=null)
|
||||
_callback.succeeded();
|
||||
}
|
||||
|
||||
|
||||
boolean isCallbackNonBlocking()
|
||||
{
|
||||
return _callback!=null && _callback.isNonBlocking();
|
||||
|
@ -280,7 +280,7 @@ abstract public class WriteFlusher
|
|||
State s = _state.get();
|
||||
return (s instanceof PendingState) && ((PendingState)s).isCallbackNonBlocking();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Abstract call to be implemented by specific WriteFlushers. It should schedule a call to {@link #completeWrite()}
|
||||
* or {@link #onFail(Throwable)} when appropriate.
|
||||
|
@ -355,7 +355,7 @@ abstract public class WriteFlusher
|
|||
* {@link #onFail(Throwable)} or {@link #onClose()}
|
||||
*/
|
||||
public void completeWrite()
|
||||
{
|
||||
{
|
||||
if (DEBUG)
|
||||
LOG.debug("completeWrite: {}", this);
|
||||
|
||||
|
@ -404,8 +404,9 @@ abstract public class WriteFlusher
|
|||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Flush the buffers iteratively until no progress is made
|
||||
/**
|
||||
* Flushes the buffers iteratively until no progress is made.
|
||||
*
|
||||
* @param buffers The buffers to flush
|
||||
* @return The unflushed buffers, or null if all flushed
|
||||
* @throws IOException if unable to flush
|
||||
|
@ -418,15 +419,15 @@ abstract public class WriteFlusher
|
|||
int before=buffers.length==0?0:buffers[0].remaining();
|
||||
boolean flushed=_endPoint.flush(buffers);
|
||||
int r=buffers.length==0?0:buffers[0].remaining();
|
||||
|
||||
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Flushed={} {}/{}+{} {}",flushed,before-r,before,buffers.length-1,this);
|
||||
|
||||
|
||||
if (flushed)
|
||||
return null;
|
||||
|
||||
|
||||
progress=before!=r;
|
||||
|
||||
|
||||
int not_empty=0;
|
||||
while(r==0)
|
||||
{
|
||||
|
@ -442,17 +443,17 @@ abstract public class WriteFlusher
|
|||
|
||||
if (not_empty>0)
|
||||
buffers=Arrays.copyOfRange(buffers,not_empty,buffers.length);
|
||||
}
|
||||
}
|
||||
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("!fully flushed {}",this);
|
||||
|
||||
|
||||
// If buffers is null, then flush has returned false but has consumed all the data!
|
||||
// This is probably SSL being unable to flush the encrypted buffer, so return EMPTY_BUFFERS
|
||||
// and that will keep this WriteFlusher pending.
|
||||
return buffers==null?EMPTY_BUFFERS:buffers;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Notify the flusher of a failure
|
||||
* @param cause The cause of the failure
|
||||
|
@ -494,8 +495,6 @@ abstract public class WriteFlusher
|
|||
|
||||
public void onClose()
|
||||
{
|
||||
if (_state.get()==__IDLE)
|
||||
return;
|
||||
onFail(new ClosedChannelException());
|
||||
}
|
||||
|
||||
|
@ -522,7 +521,7 @@ abstract public class WriteFlusher
|
|||
{
|
||||
return String.format("WriteFlusher@%x{%s}", hashCode(), _state.get());
|
||||
}
|
||||
|
||||
|
||||
public String toStateString()
|
||||
{
|
||||
switch(_state.get().getType())
|
||||
|
|
|
@ -29,6 +29,7 @@ import javax.net.ssl.SSLEngineResult;
|
|||
import javax.net.ssl.SSLEngineResult.HandshakeStatus;
|
||||
import javax.net.ssl.SSLEngineResult.Status;
|
||||
import javax.net.ssl.SSLException;
|
||||
import javax.net.ssl.SSLHandshakeException;
|
||||
|
||||
import org.eclipse.jetty.io.AbstractConnection;
|
||||
import org.eclipse.jetty.io.AbstractEndPoint;
|
||||
|
@ -589,7 +590,7 @@ public class SslConnection extends AbstractConnection
|
|||
{
|
||||
_handshaken = true;
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("{} {} handshook {}/{}", SslConnection.this,
|
||||
LOG.debug("{} {} handshake succeeded {}/{}", SslConnection.this,
|
||||
_sslEngine.getUseClientMode() ? "client" : "resumed server",
|
||||
_sslEngine.getSession().getProtocol(),_sslEngine.getSession().getCipherSuite());
|
||||
}
|
||||
|
@ -668,17 +669,22 @@ public class SslConnection extends AbstractConnection
|
|||
}
|
||||
}
|
||||
}
|
||||
catch (IllegalStateException e)
|
||||
catch (SSLHandshakeException x)
|
||||
{
|
||||
// Some internal error in SSLEngine
|
||||
LOG.debug(e);
|
||||
close();
|
||||
throw new EofException(e);
|
||||
close(x);
|
||||
throw x;
|
||||
}
|
||||
catch (Exception e)
|
||||
catch (SSLException x)
|
||||
{
|
||||
close();
|
||||
throw e;
|
||||
if (!_handshaken)
|
||||
x = (SSLException)new SSLHandshakeException(x.getMessage()).initCause(x);
|
||||
close(x);
|
||||
throw x;
|
||||
}
|
||||
catch (Throwable x)
|
||||
{
|
||||
close(x);
|
||||
throw x;
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
@ -771,6 +777,7 @@ public class SslConnection extends AbstractConnection
|
|||
switch (wrapResultStatus)
|
||||
{
|
||||
case CLOSED:
|
||||
{
|
||||
// The SSL engine has close, but there may be close handshake that needs to be written
|
||||
if (BufferUtil.hasContent(_encryptedOutput))
|
||||
{
|
||||
|
@ -790,11 +797,13 @@ public class SslConnection extends AbstractConnection
|
|||
getEndPoint().shutdownOutput();
|
||||
}
|
||||
return allConsumed;
|
||||
|
||||
}
|
||||
case BUFFER_UNDERFLOW:
|
||||
{
|
||||
throw new IllegalStateException();
|
||||
|
||||
}
|
||||
default:
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("{} wrap {} {}", SslConnection.this, wrapResultStatus, BufferUtil.toHexSummary(_encryptedOutput));
|
||||
|
||||
|
@ -802,7 +811,7 @@ public class SslConnection extends AbstractConnection
|
|||
{
|
||||
_handshaken = true;
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("{} server handshook complete {}/{}", SslConnection.this, _sslEngine.getSession().getProtocol(),_sslEngine.getSession().getCipherSuite());
|
||||
LOG.debug("{} server handshake succeeded {}/{}", SslConnection.this, _sslEngine.getSession().getProtocol(),_sslEngine.getSession().getCipherSuite());
|
||||
}
|
||||
|
||||
HandshakeStatus handshakeStatus = _sslEngine.getHandshakeStatus();
|
||||
|
@ -862,6 +871,17 @@ public class SslConnection extends AbstractConnection
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (SSLHandshakeException x)
|
||||
{
|
||||
close(x);
|
||||
throw x;
|
||||
}
|
||||
catch (Throwable x)
|
||||
{
|
||||
close(x);
|
||||
throw x;
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
@ -884,32 +904,27 @@ public class SslConnection extends AbstractConnection
|
|||
public void doShutdownOutput()
|
||||
{
|
||||
boolean ishut = isInputShutdown();
|
||||
boolean oshut = isOutputShutdown();
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("{} shutdownOutput: ishut={}", SslConnection.this, ishut);
|
||||
if (ishut)
|
||||
LOG.debug("{} shutdownOutput: oshut={}, ishut={}", SslConnection.this, oshut, ishut);
|
||||
try
|
||||
{
|
||||
// Aggressively close, since inbound close alert has already been processed
|
||||
// and the TLS specification allows to close the connection directly, which
|
||||
// is what most other implementations expect: a FIN rather than a TLS close
|
||||
// reply. If a TLS close reply is sent, most implementations send a RST.
|
||||
getEndPoint().close();
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
synchronized (this)
|
||||
{
|
||||
synchronized (this) // TODO review synchronized boundary
|
||||
if (!oshut)
|
||||
{
|
||||
_sslEngine.closeOutbound();
|
||||
flush(BufferUtil.EMPTY_BUFFER); // Send close handshake
|
||||
ensureFillInterested();
|
||||
// Send the TLS close message.
|
||||
flush(BufferUtil.EMPTY_BUFFER);
|
||||
if (!ishut)
|
||||
ensureFillInterested();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LOG.ignore(e);
|
||||
getEndPoint().close();
|
||||
}
|
||||
}
|
||||
catch (Throwable x)
|
||||
{
|
||||
LOG.ignore(x);
|
||||
getEndPoint().close();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -928,23 +943,8 @@ public class SslConnection extends AbstractConnection
|
|||
@Override
|
||||
public void doClose()
|
||||
{
|
||||
// First send the TLS Close Alert, then the FIN
|
||||
if (!_sslEngine.isOutboundDone())
|
||||
{
|
||||
try
|
||||
{
|
||||
synchronized (this) // TODO review synchronized boundary
|
||||
{
|
||||
_sslEngine.closeOutbound();
|
||||
flush(BufferUtil.EMPTY_BUFFER); // Send close handshake
|
||||
ensureFillInterested();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LOG.ignore(e);
|
||||
}
|
||||
}
|
||||
// First send the TLS Close Alert, then the FIN.
|
||||
doShutdownOutput();
|
||||
getEndPoint().close();
|
||||
super.doClose();
|
||||
}
|
||||
|
|
|
@ -21,7 +21,6 @@ package org.eclipse.jetty.server.ssl;
|
|||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.Socket;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
@ -60,11 +59,11 @@ import org.junit.Before;
|
|||
import org.junit.Test;
|
||||
|
||||
public class SslConnectionFactoryTest
|
||||
{
|
||||
{
|
||||
Server _server;
|
||||
ServerConnector _connector;
|
||||
int _port;
|
||||
|
||||
|
||||
@Before
|
||||
public void before() throws Exception
|
||||
{
|
||||
|
@ -84,7 +83,7 @@ public class SslConnectionFactoryTest
|
|||
HttpConfiguration https_config = new HttpConfiguration(http_config);
|
||||
https_config.addCustomizer(new SecureRequestCustomizer());
|
||||
|
||||
|
||||
|
||||
SslContextFactory sslContextFactory = new SslContextFactory();
|
||||
sslContextFactory.setKeyStorePath(keystoreFile.getAbsolutePath());
|
||||
sslContextFactory.setKeyStorePassword("OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4");
|
||||
|
@ -97,7 +96,7 @@ public class SslConnectionFactoryTest
|
|||
https.setIdleTimeout(30000);
|
||||
|
||||
_server.addConnector(https);
|
||||
|
||||
|
||||
_server.setHandler(new AbstractHandler()
|
||||
{
|
||||
@Override
|
||||
|
@ -108,30 +107,30 @@ public class SslConnectionFactoryTest
|
|||
response.flushBuffer();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
_server.start();
|
||||
_port=https.getLocalPort();
|
||||
_port=https.getLocalPort();
|
||||
}
|
||||
|
||||
|
||||
@After
|
||||
public void after() throws Exception
|
||||
{
|
||||
_server.stop();
|
||||
_server=null;
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testConnect() throws Exception
|
||||
{
|
||||
String response= getResponse("127.0.0.1",null);
|
||||
String response= getResponse("127.0.0.1",null);
|
||||
Assert.assertThat(response,Matchers.containsString("host=127.0.0.1"));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testSNIConnect() throws Exception
|
||||
{
|
||||
String response;
|
||||
|
||||
|
||||
response= getResponse("localhost","localhost","jetty.eclipse.org");
|
||||
Assert.assertThat(response,Matchers.containsString("host=localhost"));
|
||||
}
|
||||
|
@ -154,30 +153,21 @@ public class SslConnectionFactoryTest
|
|||
out.flush();
|
||||
|
||||
socket.setSoTimeout(1000);
|
||||
InputStream input = socket.getInputStream();
|
||||
int read = input.read();
|
||||
// TLS Alert message type == 21.
|
||||
Assert.assertThat(read, Matchers.equalTo(21));
|
||||
int reads = 0;
|
||||
while (read >= 0)
|
||||
{
|
||||
read = input.read();
|
||||
++reads;
|
||||
}
|
||||
Assert.assertThat(reads, Matchers.lessThan(32));
|
||||
// Expect TLS message type == 21: Alert
|
||||
Assert.assertThat(socket.getInputStream().read(),Matchers.equalTo(21));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private String getResponse(String sniHost,String reqHost, String cn) throws Exception
|
||||
{
|
||||
SslContextFactory clientContextFactory = new SslContextFactory(true);
|
||||
clientContextFactory.start();
|
||||
SSLSocketFactory factory = clientContextFactory.getSslContext().getSocketFactory();
|
||||
|
||||
|
||||
SSLSocket sslSocket = (SSLSocket)factory.createSocket("127.0.0.1", _port);
|
||||
|
||||
if (cn!=null)
|
||||
{
|
||||
{
|
||||
SNIHostName serverName = new SNIHostName(sniHost);
|
||||
List<SNIServerName> serverNames = new ArrayList<>();
|
||||
serverNames.add(serverName);
|
||||
|
@ -188,35 +178,35 @@ public class SslConnectionFactoryTest
|
|||
}
|
||||
sslSocket.startHandshake();
|
||||
|
||||
|
||||
|
||||
if (cn!=null)
|
||||
{
|
||||
{
|
||||
X509Certificate cert = ((X509Certificate)sslSocket.getSession().getPeerCertificates()[0]);
|
||||
|
||||
|
||||
Assert.assertThat(cert.getSubjectX500Principal().getName("CANONICAL"), Matchers.startsWith("cn="+cn));
|
||||
}
|
||||
|
||||
sslSocket.getOutputStream().write(("GET /ctx/path HTTP/1.0\r\nHost: "+reqHost+":"+_port+"\r\n\r\n").getBytes(StandardCharsets.ISO_8859_1));
|
||||
String response = IO.toString(sslSocket.getInputStream());
|
||||
|
||||
|
||||
sslSocket.close();
|
||||
clientContextFactory.stop();
|
||||
return response;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void testSocketCustomization() throws Exception
|
||||
{
|
||||
final Queue<String> history = new ConcurrentArrayQueue<>();
|
||||
|
||||
|
||||
_connector.addBean(new SocketCustomizationListener()
|
||||
{
|
||||
@Override
|
||||
protected void customize(Socket socket, Class<? extends Connection> connection, boolean ssl)
|
||||
{
|
||||
history.add("customize connector "+connection+","+ssl);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
_connector.getBean(SslConnectionFactory.class).addBean(new SocketCustomizationListener()
|
||||
|
@ -225,26 +215,26 @@ public class SslConnectionFactoryTest
|
|||
protected void customize(Socket socket, Class<? extends Connection> connection, boolean ssl)
|
||||
{
|
||||
history.add("customize ssl "+connection+","+ssl);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
_connector.getBean(HttpConnectionFactory.class).addBean(new SocketCustomizationListener()
|
||||
{
|
||||
@Override
|
||||
protected void customize(Socket socket, Class<? extends Connection> connection, boolean ssl)
|
||||
{
|
||||
history.add("customize http "+connection+","+ssl);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
String response= getResponse("127.0.0.1",null);
|
||||
String response= getResponse("127.0.0.1",null);
|
||||
Assert.assertThat(response,Matchers.containsString("host=127.0.0.1"));
|
||||
|
||||
|
||||
Assert.assertEquals("customize connector class org.eclipse.jetty.io.ssl.SslConnection,false",history.poll());
|
||||
Assert.assertEquals("customize ssl class org.eclipse.jetty.io.ssl.SslConnection,false",history.poll());
|
||||
Assert.assertEquals("customize connector class org.eclipse.jetty.server.HttpConnection,true",history.poll());
|
||||
Assert.assertEquals("customize http class org.eclipse.jetty.server.HttpConnection,true",history.poll());
|
||||
Assert.assertEquals(0,history.size());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue