Главная > Java сниппеты > Серверы SSL

Тема Зацепин
268

Java-разработчик 🧩
346
1 минуту

Серверы SSL

Введение Код для сервераПолучение сертификатаКод для клиента

Добавлено : 28 Dec 2008, 08:28

Содержание

Введение

В "Технических Советах" "Засекреченная связь с помощью JSSE" вы научились пользоваться безопасными HTTP запросами и ответами (известными как HTTPS или HTTP через SSL) со стороны клиента. В этой статье вы узнаете о SSL соединение со стороны сервера.

Код для сервера

Как и в предыдущей статье, "Работа с Selectors", сервер здесь будет эхо-сервером, т.е. будет просто возвращать то, что отправил клиент.

Также как и в статье, где описывалась работа со стороны клиента, чтобы создать сервер, вы сначала должны получить фабрику сокетов. Для SSL серверов – фабрика класса SSLServerSocketFactory. SSLServerSocketFactory входит в пакет javax.net.ssl.

ServerSocketFactory sslserversocketfactory =
SSLServerSocketFactory.getDefault
();

Затем вы получаете серверный сокет и ждете соединение с подтверждением:

ServerSocket serverSocket =
serverSocketFactory.createServerSocket
(PORT_NUM);
Socket socket = serverSocket.accept
();

Оставшийся код для сервера довольно простой. По аналогии со статьей "SelectorTest" вы просто читаете то, что прислал вам клиент, и отправляете обратно. Вот законченный код для сервера:

import javax.net.ssl.*;
import javax.net.*;
import java.io.*;
import java.net.*;

public class EchoServer {
private static final int PORT_NUM = 6789;

public static void main(String args[]) {
ServerSocketFactory serverSocketFactory = SSLServerSocketFactory
.getDefault
();
ServerSocket serverSocket =
null;
try {
serverSocket = serverSocketFactory.createServerSocket(PORT_NUM);
} catch (IOException ignored) {
System.err.println("Unable to create server");
System.exit
(-1);
}
while (true) {
Socket socket = null;
try {
socket = serverSocket.accept();
InputStream is = socket.getInputStream
();
BufferedReader br =
new BufferedReader(new InputStreamReader(
is, "US-ASCII"));
OutputStream os = socket.getOutputStream
();
Writer writer =
new OutputStreamWriter(os, "US-ASCII");
PrintWriter out =
new PrintWriter(writer, true);
String line =
null;
while ((line = br.readLine()) != null) {
out.println(line);
}
}
catch (IOException exception) {
exception.printStackTrace();
} finally {
if (socket != null) {
try {
socket.close();
} catch (IOException ignored) {
}
}
}
}
}
}

Получение сертификата

Запуская эту программу, возникает небольшая проблема. У вас нет сертификата. Если вы запустите программу без подтверждения сертификата, вы получите SSLException:

javax.net.ssl.SSLException: No available certificate corresponds to the SSL cipher suites which are enabled. at com.sun.net.ssl.internal.ssl.SSLServerSocketImpl.a(DashoA6275) at com.sun.net.ssl.internal.ssl.SSLServerSocketImpl.accept(DashoA6275) at EchoServer.main(EchoServer.java:21)

Вы можете сгенерировать сертификат с помощью программы keytool, которая поставляется с SDK. Выберете в keytool опцию -genkey, чтобы создать keypair (пару ключей), затем опцию -keystore, чтобы определить место файла с ключом и опцию -keyalg, чтобы определить алгоритм шифрования:

 keytool -genkey -keystore testStore -keyalg RSA

В ответ вы получите информацию. Применяйте информацию по обстановке. Вот как может выглядеть диалог:

 Enter keystore password: tutorial What is your first and last name? [Unknown]: Sun Tutorial What is the name of your organizational unit? [Unknown]: Sun What is the name of your organization? [Unknown]: Sun What is the name of your City or Locality? [Unknown]: Santa Clara What is the name of your State or Province? [Unknown]: CA What is the two-letter country code for this unit? [Unknown]: US Is CN=Sun Tutorial, OU=Sun, O=Sun, L=Santa Clara, ST=CA, C=US correct? [no]: yes Enter key password for <mykey> (RETURN if same as keystore password):

Обычно в CN (имя и фамилия) пишут имя хоста сервера, хотя это и не обязательное требование. В этом примере это имя используется, потому что клиент имеет доступ к серверу по локальному хосту.

После запуска команды у вас появится новый файл с названием testStore в вашей рабочей директории. Теперь вы можете запустить сервер с помощью SSL. При запуске сервера, вы указываете хранилище ключа с помощью свойства javax.net.ssl.keyStore, а его пароль с помощью свойства javax.net.ssl.keyStorePassword.

 java -Djavax.net.ssl.keyStore=testStore -Djavax.net.ssl.keyStorePassword=tutorial EchoServer

Код для клиента

Конечно, нужен клиент, который будет общаться с сервером. Ниже приведен клиент, который читает входные данные из командной строки, посылает их серверу и пишет ответ сервера:

import javax.net.ssl.*;
import javax.net.*;
import java.io.*;
import java.net.*;

public class EchoClient {
private static int PORT_NUM = 6789;
private static String host = "localhost";

public static void main(String args[]) throws IOException {
SocketFactory socketFactory = SSLSocketFactory.getDefault();
Socket socket = socketFactory.createSocket
(host, PORT_NUM);

BufferedReader br =
new BufferedReader(new InputStreamReader(System.in,
"US-ASCII"));
PrintWriter out =
new PrintWriter(new OutputStreamWriter(socket
.getOutputStream
(), "US-ASCII"), true);

BufferedReader socketBr =
new BufferedReader(new InputStreamReader(
socket.getInputStream(), "US-ASCII"));

String string =
null;
System.out.print
("First line: ");
while (!(string = br.readLine()).equals("")) {
out.println(string);
String line = socketBr.readLine
();
System.out.println
("Got Back: " + line);
System.out.print
("Next line: ");
}
socket.close();
}
}

Скомпилируйте клиент. Для запуска клиента вам нужно указать тот же сертификат, который вы указывали, когда запускали вервер. С другой стороны, вы получаете исключение SSLHandshakeException на сервере, когда клиент пытается подключиться к серверу:

 javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake

Когда вы запускаете клиента, вы представляете сертификат как доверительное хранилище (trust store), в отличие от хранилища ключа:

 java -Djavax.net.ssl.trustStore=testStore -Djavax.net.ssl.trustStorePassword=tutorial EchoClient

Теперь клиент будет общаться с вервером через SSL.

First line: HelloПервая строка: Hello
Got Back: HelloОтвет: Hello
Next line: ThereСледующая строка: There
Got Back: ThereОтвет: There
Next line: ServerСледующая строка: Server
Got Back: ServerОтвет: Server

На одной машине разделить сертификат просто. Однако, разделение сертификата на нескольких машинах требует получение сертификата для другой (клиетнской) машины. Вы можете просто скопировать хранилище ключа "testStore", одноко, это раскроет ваши приватные ключи. Потом кто-нибудь может выдать себя за вас. В место этого используйте опции -export и -import программы keytool. Вы экспортируете сертификат, который можно публиковать. Затем кто-то, кто доверяет вам, импортирует его на свою машину. Это можно сделать несколько раз для нескольких машин. После импорта сертификата на другую машину, клиент на этой машине может общаться с вами через SSL.

За дополнительной информацией по использованию SSL, смотрите "Java Secure Socket Extension (JSSE) Reference Guide".

Теги: j2eeserversSSL

Еще от автора

Применение WeakHashmap для списков слушателей

В статье от 11мая 1999 года Reference Objects были описаны основные идеи применения ссылочных объектов, но не приводилось детального описания. Данная статья позволит вам получить больше сведений, касающихся данной темы. В основном ссылочные объекты применяются для косвенных ссылок на память необходимую объектам. Ссылочные объекты хранятся в очереди (класс ReferenceQueue), в которой отслеживается доступность ссылочных объектов. Исходя из типа ссылочного объекта, сборщик мусора может освобождать память даже тогда, когда обычные ссылки не могут быть освобождены.

Заставки в Mustang

Согласно определению, данному в Wikipedia, заставка - это компьютерный термин, обозначающий рисунок, появляющийся во время загрузки программы или операционной системы. Заставка для пользователя является визуальным отображением инициализации программы. До выхода версии Java SE 6 (кодовое название Mustang) единственной возможностью применения заставки было создание окна, во время запуска метода main, и размещение в нем картинки. Хотя данный способ и работал, но он требовал полной инициализации исполняемой Java среды до появления окна заставки. При инициализации загружались библиотеки AWT и Swing, таким образом, появление заставки задерживалось. В Mustang появился новый аргумент командной строки, значительно облегчающий использование заставок. Этот способ позволяет выводить заставку значительно быстрее до запуска исполняемой Java среды. Окончательное добавление данной функциональности находится на рассмотрении в JCP.

Совмещение изображений

1 Введение 2 Правила визуализации и пример 3 Совмещение изображений в оперативной памяти 4 Постепенное исчезновение изображения 5 Ссылки и дополнительная информация

Еще по теме

Применение WeakHashmap для списков слушателей

В статье от 11мая 1999 года Reference Objects были описаны основные идеи применения ссылочных объектов, но не приводилось детального описания. Данная статья позволит вам получить больше сведений, касающихся данной темы. В основном ссылочные объекты применяются для косвенных ссылок на память необходимую объектам. Ссылочные объекты хранятся в очереди (класс ReferenceQueue), в которой отслеживается доступность ссылочных объектов. Исходя из типа ссылочного объекта, сборщик мусора может освобождать память даже тогда, когда обычные ссылки не могут быть освобождены.

Заставки в Mustang

Согласно определению, данному в Wikipedia, заставка - это компьютерный термин, обозначающий рисунок, появляющийся во время загрузки программы или операционной системы. Заставка для пользователя является визуальным отображением инициализации программы. До выхода версии Java SE 6 (кодовое название Mustang) единственной возможностью применения заставки было создание окна, во время запуска метода main, и размещение в нем картинки. Хотя данный способ и работал, но он требовал полной инициализации исполняемой Java среды до появления окна заставки. При инициализации загружались библиотеки AWT и Swing, таким образом, появление заставки задерживалось. В Mustang появился новый аргумент командной строки, значительно облегчающий использование заставок. Этот способ позволяет выводить заставку значительно быстрее до запуска исполняемой Java среды. Окончательное добавление данной функциональности находится на рассмотрении в JCP.

Использование потоков

1 Введение 2 Работа с выражениями типа Boolean 3 Класс JoptionPane 4 Приложение-счетчик 5 Ссылки

Перехват необрабатываемых исключений

В статье от 16 марта 2004 года Best Practices in Exception Handling были описаны приемы обработки исключений. В данной статье вы изучите новый способ обработки исключений при помощи класса UncaughtExceptionHandler добавленного в J2SE 5.0.

Использование класса LinkedHashMap

1 Введение 2 Сортировка хэш-таблицы 3 Копирование таблицы 4 Сохранение порядка доступа к элементам 5 Ссылки

Сказ про кодировки и java

С кодировками в java плохо. Т.е., наоборот, все идеально хорошо: внутреннее представление строк – Utf16-BE (и поддержка Unicode была с самых первых дней). Все возможные функции умеют преобразовывать строку из маленького регистра в большой, проверять является ли данный символ буквой или цифрой, выполнять поиск в строке (в том числе с регулярными выражениями) и прочее и прочее. Для этих операций не нужно использовать какие-то посторонние библиотеки вроде привычных для php mbstring или iconv. Как говорится, поддержка многоязычных тестов “есть в коробке”. Так откуда берутся проблемы? Проблемы возникают, как только строки текста пытаются “выбраться” из jvm (операции вывода текста различным потребителям) или наоборот пытаются в эту самую jvm “залезть” (операция чтения данных от некоторого поставщика).