Статьи

Сквозная безопасность JavaDB

JavaDB , как реляционная база данных с открытым исходным кодом и чисто Java, предоставляет несколько функций, которые делают ее подходящей для режимов встроенного и сетевого сервера, включая механизмы JavaDB для обеспечения ее безопасности на нескольких уровнях. Если вы собираетесь создавать приложение с использованием JavaDB и безопасность важна, тогда эта статья для вас.

Вот шаги, которые мы должны выполнить, чтобы заставить JavaDB работать с приемлемым уровнем безопасности:

  1. Применяйте шифрование для защиты файлов базы данных физически.
  2. Примените аутентификацию для соединений, чтобы ограничить доступ к нашему серверу.
  3. Примените авторизацию SQL для внутреннего управления разрешениями для объектов базы данных.
  4. Защитите среду, используя менеджер безопасности Java.

Прежде чем мы углубимся в каждую из этих тем, вам необходимо установить JavaDB в вашей среде. В целях аутентификации мы будем использовать OpenDS , который является чистым Java-сервером LDAP с открытым исходным кодом.

Я расскажу о каждом из вышеперечисленных пунктов и в то же время предоставлю вам подробные инструкции по его решению с использованием функций, предоставляемых JavaDB.

Шифрование базы данных

Во-первых, давайте посмотрим, что мы имеем, когда создаем базу данных в JavaDB. База данных JavaDB обычно представляет собой каталог, содержащий некоторые файлы данных, журналы транзакций и файл конфигурации базы данных, service.properties . Каталог базы данных JavaDB является переносимым, и любой может скопировать базу данных JavaDB и загрузить ее, используя другой экземпляр JavaDB, и просмотреть ее данные. Но есть некоторые механизмы, которые защищают нашу базу данных от любого внешнего несанкционированного доступа. База данных JavaDB может быть зашифрована на жестком диске и, следовательно, не может использоваться до расшифровки. Расшифровка возможна только с использованием одного ключа или пароля, который предоставляется при создании базы данных.

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

Возможно, вы уже знаете, что мы можем создать базу данных, предоставив дополнительные атрибуты в строке подключения JDBC. Чтобы продемонстрировать наши шаги, я буду использовать IJ — инструмент командной строки JavaDB для администрирования и разработки баз данных. Запустите сетевой сервер JavaDB, а затем запустите интерфейс командной строки ij и выполните следующие команды одну за другой. Я должен сказать, что в этой статье мы будем использовать скрипт NetworkServerControl для запуска и остановки сетевого сервера. Вы можете запустить сетевой сервер, передавая start в качестве аргумента командной строки для запуска JavaDB.

F:\dev\dbServers\JavaDB-10.2.2.0\bin>ij
ij version 10.2
ij> DRIVER 'org.apache.derby.jdbc.ClientDriver';
ij> CONNECT 'jdbc:derby://127.0.0.1/secArticle;create=true;dataEncryption=true;bootPassword=a@Simple_More_Than_16_Char_Password;encryptionAlgorithm=Blowfish/CBC/NoPadding;user=tquist';
ij>

 

Первая команда, DRIVER, сообщает ij, какой драйвер ей следует использовать, а вторая команда создает зашифрованную базу данных. Владелец нашей базы данных — tquist ; указывать пользователя не обязательно, но мы указываем его, потому что на следующих нескольких шагах мы поговорим о владении базой данных.

Внутри строки подключения вы можете видеть три атрибута, с которыми вы, возможно, не знакомы:

  • dataEncryption: Этот атрибут просто указывает сетевому серверу создать зашифрованную базу данных.

  • bootPassword: это пароль, который будет использоваться для шифрования ключа, который механизм JavaDB использует для шифрования файлов данных. Длина пароля должна соответствовать длине ключа алгоритма, и в нашем случае она должна иметь 16 или более символов, поскольку Blowfish является 128-битным алгоритмом шифрования.

  • encryptionAlgorithm: определяет, какой алгоритм и конфигурацию следует использовать для шифрования базы данных.

Теперь у нас есть зашифрованная база данных, и нам нужно подключиться к этой базе данных из нашего приложения Java, как выглядит код, который подключается к этой зашифрованной базе данных? Это довольно просто: вам просто нужно включить атрибут bootPassword в строку подключения. Что-то вроде этого:

...
class.forName("org.apache.derby.jdbc.ClientDriver").newInstance();
Connection connection =
DriverManager.getConnection ("jdbc:derby://127.0.0.1/secArticle;bootPassword=a@Simple_More_Than_16_Char_Password");
...

Это оно; у вас есть подключение к вашей зашифрованной базе данных. Помните, что после загрузки базы данных (т. Е. Вы установили первое соединение с паролем загрузки), она будет открыта для соединений даже без bootPassword. Поэтому закройте базу данных, как только вы закончите работу с ней. Следующий фрагмент кода показывает, как вы можете закрыть базу данных из вашего приложения.

   boolean cantShutdown = false;
try {
DriverManager.getConnection("jdbc:derby:;shutdown=true");
} catch (SQLException se) {
if ( se.getSQLState().equals("XJ015") ) {
cantShutdown = true;
}
}
if (!cantShutdown ) {
//Your database did not shutdown properly
} else {
//Your database is shutdown
}


Если вы попытаетесь подключиться к базе данных без атрибута bootPassword, вы получите сообщение об ошибке. Используя шифрование, вы защищаете свою базу данных от любого внешнего несанкционированного доступа со стороны любого, кто не знает пароль загрузки.

Аутентификация соединения

В качестве второй проблемы я собираюсь поговорить об аутентификации соединения . База данных или сервер JavaDB открыта для соединений с полным доступом ко всем ресурсам сервера базы данных. Разработчик базы данных может настроить его для аутентификации пользователей, которые пытаются подключиться к базе данных на сервере. До тех пор, пока вы не попытаетесь настроить его в соответствии с вашими конкретными потребностями, JavaDB является СУБД без администрирования. Но настройка JavaDB для выполнения аутентификации очень проста и практически не требует затрат.

Сетевой сервер JavaDB настраивается с использованием стандартного файла свойств с именем derby.properties , который можно просто поместить в каталог bin JavaDB . Есть десятки параметров конфигурации, которые мы можем поместить в этот файл свойств, но сейчас мы просто собираемся использовать некоторые из них.

JavaDB может аутентифицировать пользователей тремя способами в дополнение к стандартному поведению без авторизации:

  • Встроенный
  • Внешний LDAP
  • Применение определенных

Каждый из перечисленных механизмов имеет свои сильные и слабые стороны; в следующих нескольких параграфах вы увидите, как легко вы можете настроить JavaDB для выполнения аутентификации на основе внешнего LDAP, такого как OpenDS.

Прежде чем мы продолжим, вам нужно настроить и запустить сервер каталогов OpenDS. OpenDS — это чистый Java-сервер каталогов с открытым исходным кодом, имеющий множество функций, которые можно использовать для создания корпоративных приложений. Установка OpenDS проста: просто запустите установщик QuickSetup JNLP (Java Web Start) и следуйте инструкциям по установке, чтобы настроить сервер каталогов.

Установив OpenDS, я опишу тестовые данные, которые вы импортируете в хранилище сервера каталогов для проверки аутентификации JavaDB. Наши тестовые данные — это стандартный файл LDIF, который вы можете найти в разделе « Ресурсы ». Вы можете импортировать его в OpenDS, используя его скрипт оболочки с именем import-ldif .

>import-ldif --backendID userRoot --ldifFile path/to/secArticle.LDIF

Выполнив вышеуказанную команду в каталоге бина OpenDS , вы можете импортировать данные примера в хранилище сервера каталогов. Убедитесь, что OpenDS не работает, когда вы хотите импортировать данные в его хранилище; в противном случае вы получите сообщение об ошибке, указывающее, что утилита импорта не может получить блокировку для хранилища.

Если вы просматриваете хранилище OpenDS с помощью браузера LDAP, такого как LDAP Studio , вы найдете четыре записи в разделе dc = example, dc = com. Эти записи являются пользователями, которые мы будем использовать в следующих частях этой статьи. Имена пользователей: jhallett , mchrysta , thardy и tquist ; их пароли совпадают с соответствующими именами пользователей.

Для активации аутентификации нам нужно добавить свойство в файл derby.properties . Создайте текстовый файл и сохраните его в JavaDB_home / bin как derby.properties , откройте файл и добавьте в него следующую строку.

derby.connection.requireAuthentication=true

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

derby.authentication.server=ldap://127.0.0.1:389
derby.authentication.provider=LDAP
derby.authentication.ldap.searchAuthPW=YOUR_SELECTED_PASSWORD
derby.authentication.ldap.searchAuthDN=cn=Directory Manager
derby.authentication.ldap.searchBase=dc=example,dc=com
derby.authentication.ldap.searchFilter=objectClass=person

 

Не обязательно добавлять все вышеперечисленные свойства, но рекомендуется включать последние два, так как они ограничивают область поиска имен пользователей во время аутентификации. Объяснение каждого из этих атрибутов можно найти в документации JavaDB .

Теперь перезапустите сетевой сервер JavaDB и попробуем подключиться к нашей базе данных secArticle, как на предыдущем шаге, чтобы увидеть, что мы получим, когда попробуем. Откройте сеанс ij и выполните следующие команды.

ij> DRIVER 'org.apache.derby.jdbc.ClientDriver';
ij> CONNECT 'jdbc:derby://127.0.0.1/secArticle;bootPassword=a@Simple_More_Than_16_Char_Password;user= tquist';
ERROR 08004: Connection authentication failure occurred. Reason: userid or password invalid.

 

Теперь давайте предоставим правильное имя пользователя и пароль; мы можем использовать любого из четырех пользователей, которых мы добавили в наше хранилище OpenDS в предыдущем разделе.

ij> CONNECT 'jdbc:derby://127.0.0.1/secArticle;bootPassword=a@Simple_More_Than_16_Char_Password;user=tquist;password=tquist'; 
ij>

 

На этот раз вы сможете без проблем подключиться к базе данных.

SQL авторизация

Теперь у нас есть аутентификация в развертывании; что насчет авторизации? Активировать авторизацию JavaDB SQL очень просто; просто откройте derby.properties и добавьте несколько записей, которые просят JavaDB применить авторизацию SQL. Вы должны добавить следующие строки:

derby.database.sqlAuthorization=true
derby.database.defaultConnectionMode=sqlStandard

Эти два свойства обеспечивают авторизацию SQL для любой базы данных, созданной с этого момента. Но как насчет наших уже созданных баз данных? Что мы можем сделать, чтобы включить в них авторизацию SQL? К счастью, нам просто нужно выполнить системную функцию, чтобы установить авторизацию SQL для уже созданной базы данных. Откройте сеанс IJ, подключитесь к нашей базе данных и выполните следующую команду.

ij> CALL SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY('derby.database.sqlAuthorization','true');

Теперь наша база данных имеет возможность авторизации SQL, но сетевой сервер должен быть перезапущен, прежде чем мы сможем использовать эту функцию. Перезагрузите сетевой сервер и продолжите. Затем откройте сеанс ij, подключитесь к базе данных с пользователем tquist и создайте таблицу.

ij> CONNECT 'jdbc:derby://127.0.0.1/secArticle;bootPassword=a@Simple_More_Than_16_Char_Password; user=tquist;password= tquist';
ij> CREATE TABLE sec_art_table ( name VARCHAR(25) , lastName VARCHAR(25));
0 rows inserted/updated/deleted
ij> disconnect;

Выполнение вышеуказанных команд создаст таблицу в схеме TQUIST с владельцем таблицы tquist , у которого есть полные права на эту таблицу. Последняя команда завершит текущий сеанс.

Теперь, чтобы проверить, безопасна ли наша таблица, подключитесь к базе данных с другим пользователем и попытайтесь вставить некоторые данные в эту таблицу.

ij> CONNECT 'jdbc:derby://127.0.0.1/secArticle;bootPassword=a@Simple_More_Than_16_Char_Password;user= jhallett;password=jhallett';
ij> INSERT INTO TQUIST.sec_art_table values ( ‘John' ,'Connor');
ERROR 28506: User 'JHALLETT' does not have insert permission on table 'TQUIST'.'
SEC_ART_TABLE'.
ij>disconnect;

Вышеуказанная ошибка указывает на то, что наш пользователь не имеет прав на выполнение вставки в TQUIST.sec_art_table. В следующем фрагменте кода мы подключаемся к базе данных как пользователь tquist и предоставляем некоторые разрешения jhallett .

ij> CONNECT 'jdbc:derby://127.0.0.1/secArticle;bootPassword=a@Simple_More_Than_1
6_Char_Password; user=tquist;password= tquist';
ij> grant insert on TQUIST.sec_art_table to jhallett;
0 rows inserted/updated/deleted

 

Теперь у jhallett есть права на вставку в TQUIST.sec_art_table. Вы можете попробовать вставить оператор снова, чтобы убедиться, что он работает нормально. Другие реализованные и поддерживаемые привилегии можно найти в документации JavaDB.

Защита окружающей среды

Диспетчер безопасности Java и определение политики — это механизм, который позволяет определять и применять определенные политики в отношении выполнения определенного кода и доступа JVM к некоторым потенциально опасным ресурсам, таким как сокеты, файлы и т. Д. По умолчанию при установке JRE или JDK ограничений нет, и все разрешения предоставляются стандартным расширениям.

На уровне JVM у нас может быть одна реализация политики по умолчанию, которая будет применяться ко всем пользователям этой JRE. Мы также можем определить файлы политик для каждого пользователя, чтобы применять определенные политики для определенных пользователей. Существует несколько способов применения политик к JVM, но наиболее популярным является использование файлов политик, которые мы передаем команде java. Файл политики — это простой текстовый файл в кодировке UTF-8, который соответствует стандартному синтаксису объявления политики. Обсуждение файлов политики и менеджера безопасности выходит за рамки этой статьи, поэтому давайте вернемся к настройке безопасности для среды JavaDB.

Когда вы запускаете сетевой сервер JavaDB, вы можете активировать диспетчер безопасности Java и передать файл политики в JVM для использования во время его работы. Для этого вы можете либо отредактировать файл оболочки NetworkServerControl (файл .bat или .sh), либо напрямую выполнить класс NetworkServerControl и передать требуемый параметр JRE. Я, например, предпочитаю редактировать командный файл NetworkServerControl . Посмотрите на файл NetworkServerControl.bat, и вы найдете такой блок кода:

:runWithClasspath
"%_JAVACMD%" %DERBY_OPTS% -classpath "%CLASSPATH%;%LOCALCLASSPATH%" org.apache.derby.drda.NetworkServerControl %DERBY_ARGS% %DERBY_CMD_LINE_ARGS%
goto end

 

Вам просто нужно изменить среднюю линию на:

:runWithClasspath
"%_JAVACMD%" -Djava.security.manager -Djava.security.policy=JavaDB.policy -classpath "%CLASSPATH%;%LOCALCLASSPATH%" org.apache.derby.drda.NetworkServerControl %DERBY_ARGS% %DERBY_CMD_LINE_ARGS%
goto end

 

Как я уже сказал, файл политики — это простой текстовый файл, поэтому создайте текстовый файл и сохраните его как JavaDB.policy в каталоге bin JavaDB . Теперь добавьте следующий фрагмент к нему.

grant codeBase "file:F:/dev/dbServers/JavaDB-10.2.2.0/lib/*" {
permission java.io.FilePermission "${derby.system.home}", "read";
permission java.io.FilePermission "${derby.system.home}${/}-", "read, write, delete";
permission java.io.FilePermission "${user.dir}${/}-", "read, write, delete";
permission java.util.PropertyPermission "derby.*", "read";
permission java.util.PropertyPermission "user.dir", "read";
permission java.lang.RuntimePermission "createClassLoader";
permission java.net.SocketPermission "localhost", "accept";
permission java.net.SocketPermission "127.0.0.1", "accept, connect,resolve";
};

 

В приведенном выше описании политики. мы предоставляем некоторые разрешения всем файлам и классам .jar, размещенным в папке lib ; разрешения следующие:

  • Мы предоставляем полный доступ через домашний каталог JavaDB и его подкаталоги; например, классы JavaDB имеют полный доступ к каталогу bin , в котором находится наша база данных.
  • Разрешение на чтение для чтения свойства user.dir и всех свойств JavaDB.
  • Мы разрешаем создание загрузчика классов, который позволяет JavaDB выполнять запросы и загружать необходимые классы.
  • Мы разрешаем кодовой базе создавать сокеты и принимать соединения с локального и петлевого IP-адресов.

По умолчанию сетевой сервер JavaDB будет прослушивать localhost , но мы можем передать аргумент -h AN_IP_ADDRESS в NetworkServerControl, чтобы настроить его на прослушивание других IP-адресов. Теперь представьте, что ваша JavaDB открыта для входящих соединений из Интернета; вы можете просто ограничить количество входящих подключений к вашему сетевому серверу JavaDB, указав список разрешенных адресов в файле политики, как мы сделали в нашем примере файла политики.

Вывод

JavaDB, как база данных на чистом Java с открытым исходным кодом, может сыграть важную роль в будущих Java-приложениях, особенно для небольших приложений, которым не нужен огромный список дорогих функций, доступных в коммерческих RDBMS. Безопасность является серьезной проблемой для индустрии разработки программного обеспечения, и JavaDB предоставляет приемлемый набор функций для обеспечения безопасности вашей небольшой базы данных.

Некоторые вопросы, с которыми вы можете столкнуться во время этой статьи

Что произойдет, если я предоставлю привилегию (и) пользователю, которого не существует?

Ничего такого;
вы не получите исключение или сообщение об ошибке. Привилегии будут предоставлены пользователю, поскольку JavaDB не проверяет ваш источник аутентификации на наличие пользователя, когда вы предоставляете пользователю некоторые привилегии.
Кто является администратором базы данных?

Пользователь, который создает базу данных, является
администратором базы данных , то есть пользователь имеет возможность предоставлять или отзывать привилегии других пользователей в любой схеме. Каждый пользователь имеет полный доступ к своей схеме.
Можем ли мы использовать наш собственный алгоритм для шифрования JavaDB?

Да, вы можете использовать свой собственный алгоритм, но он должен соответствовать некоторым критериям.
Взгляните на
Java Cryptography Extension (JCE) и документацию по
определению альтернативного алгоритма шифрования .
Что такое переменная derby.system.home?

Это переменная среды, используемая для указания каталога, в котором будет запускаться JavaDB.
По умолчанию JavaDB запускается в своем
каталоге
bin , поэтому
derby.system.home по умолчанию является каталогом JavaDB
bin .