«Старое» решение
Сначала воспроизведем пример из упомянутой выше по тексту первой статьи с тою разницей, что теперь функция политики доступа к таблице SCOTT.EMP и вспомогательная таблица, регулирующая доступ, создаются в отдельной схеме VPD_ADMIN «администратора политик» (что в методологически более правильно):
CONNECT vpd_admin/vpd_admin
Таблица с данными, параметризующими доступ:
CREATE TABLE permissions_table ( username VARCHAR2(14) , deptno NUMBER (2) );
INSERT INTO permissions_table VALUES ('SCOTT', 10);
INSERT INTO permissions_table VALUES ('SCOTT', 30);
INSERT INTO permissions_table VALUES ('ADAM', 10);
(Полагаем, что пользователь SCOTT будет работать с сотрудниками 10-го и 30-го отделов, а пользователь ADAM – с сотрудниками только 10-го).
Функция, служащая предикатом доступа, задающая фильтр для строк при обращении к таблице SCOTT.EMP:
CREATE OR REPLACE FUNCTION permissions_function ( obj_schema IN VARCHAR2 ,obj_name IN VARCHAR2 ) RETURN VARCHAR2 IS BEGIN RETURN 'deptno IN (SELECT deptno FROM permissions_table ' 'WHERE username = USER)'; END; /
Политику доступа к таблице SCOTT.EMP по-прежнему назовем EPOLICY:
BEGIN DBMS_RLS.ADD_POLICY ( POLICY_NAME => 'epolicy' ,OBJECT_SCHEMA => 'scott' ,OBJECT_NAME => 'emp' ,FUNCTION_SCHEMA => 'vpd_admin' ,POLICY_FUNCTION => 'permissions_function' ); END; /
GRANT EXECUTE ON permissions_function TO scott;
Проверка:
SQL> CONNECT scott/tiger Connected. SQL> SELECT ename, sal, deptno FROM emp;
ENAME SAL DEPTNO
---------- ---------- ---------- MILLER 1300 10
KING 5000 10
CLARK 2450 10
JAMES 950 30
TURNER 1500 30
BLAKE 2850 30
MARTIN 1250 30
WARD 1250 30
ALLEN 1600 30
9 rows selected.
Новые параметры политики доступа в версии 10
В версии 10.1 у процедуры DBMS_RLS.ADD_POLICY появились новые необязательные (умолчательное значение – NULL) параметры:
Параметр SEC_RELEVANT_COLS
Здесь через запятую указываются столбцы таблицы, содержащие, по нашему хотению, данные ограниченного доступа. Если при обращении к таблице мы обратимся к этим столбцам, значений в них не увидим. Пример:
Не совсем очевидными могут представиться правила видимости строк. Так обратите внимание, что политика EPOLICY ограничивает пользователю SCOTT доступ к строкам даже собственной таблицы ! Возможно это не самый реалистичный пример, и чаще разработчик будет помещать таблицу с данными в отдельную схему, но таковы свойства VPD. С другой стороны, пользователь SYS имеет доступ ко всем данным любой таблицы вне зависимости от того, связана с ней какая-нибудь политика или нет. Точнее, не замечать политики будет любой пользователь, обладающей привилегией EXEMPT ACCESS POLICY (проверьте это !).
Обращает на себя внимание содержательная упрощенность примера выше. Отчасти она намеренная, а отчасти вынужденная. Например, прямолинейная попытка реализовать более интересный вариант, при котором каждый сотрудник будет «видеть» строки только о себе и о своих подчиненных, обречена на неудачу, в чем легко убедиться. Действительно, формулирование в функции-предикате условия отбора, содержащее упоминание самой таблицы EMP (что потребуется, если мы захотим отбирать из EMP строки с подчиненными) приведет к рекурсивному обращению к политике EPOLICY, то есть к ошибке. Как поступить в этом случае ?
Во-первых, создать отдельную таблицу, наподобие того, как это сделано выше, и перенести в нее нужные данные из EMP.
Во-вторых, создать не новую таблицу, а materialized view на основе EMP, и в функции-предикате обращаться именно к materialized view. Это будет технологичнее, так как снимет проблему синхронизации данных во вспомогательной таблице с изменениями в EMP. Materialized view в этом случае удобно создать со свойством REFRESH ON COMMIT.
К сожалению, в любом случае придется дублировать часть данных из основной таблицы EMP.
Ну, и наконец, в реальной практике эффективно использовать контекст сеанса, хотя это и усложнит программирование.
1. Формально не эквивалент, так как документация по Oracle считает, что VPD = FGAC + контекст приложения. По существу же мне разницы не видится.
Хотя формально этого не требуется, при использовании VPD методологически правильно завести специального пользователя-администратора. Ниже ему предоставляется минимум полномочий, достаточных для примеров из этой статьи. Выдаем в SQL*Plus:
CONNECT / AS SYSDBA
CREATE USER vpd_admin IDENTIFIED BY vpd_admin DEFAULT TABLESPACE sysaux TEMPORARY TABLESPACE temp QUOTA UNLIMITED ON sysaux;
GRANT CREATE SESSION TO vpd_admin;
GRANT CREATE PROCEDURE TO vpd_admin;
GRANT CREATE TABLE TO vpd_admin;
GRANT EXECUTE ON dbms_rls TO vpd_admin;
Владимир Пржиялковский
Преподаватель технологий Oracle
Если на клетке буйвола прочтешь "Слон" – не верь глазам своим.
Козьма Прутков
Рассматривается использование электронного бумажника Oracle Wallet для защиты от прочтения данных на внешнем носителе путем прозрачного шифрования (TDE) содержимого столбцов таблиц и табличных пространств, а также путем шифрования резервных копий.
Преподаватель технологий Oracle
http://open.oracle.tu2.ru/.index
Ноябрь 2008 г.
Держи карман шире!
Крылатое выражение
Бумажник Oracle Wallet представляет собой двоичный файл, составленный по промышленному стандарту PKCS #12 «синтаксиса обмена персональной информацией» (), что обеспечивает ему совместимость с ПО третьих фирм. Файл имеет имя ewallet.p12, и он должен располагаться в любом доступном СУБД каталоге файловой системы. Тем не менее, когда бумажник используется для хранения главного ключа шифрования (о чем речь в этой статье), имеется умолчательное местонахождение (не требующее явного указания): по системе обозначений Windows это %ORACLE_BASE %\admin\%ORACLE_SID%\wallet. (Оно разумно привязано к месту хранения рабочих файлов СУБД, так как несколько СУБД на одном компьютере не имеют права пользоваться общим бумажником).
Сам бумажник Oracle появился в версии 8.1, однако приводимое далее его применение оказалось возможным только в версии 10.2.
Для работы со своим электронным бумажником фирма Oracle дает следующие средства:
команды SQL; программу Oracle Wallet Manager (она же owm);
программу orapki;
программу mkstore.
Три последние суть обращения к методам main классов Java, соответственно:
oracle.security.admin.wltmgr.owma.OwmaApp, oracle.security.pki.textui.OraclePKITextUI, oracle.security.pki.OracleSecretStoreTextUI.
(Все они, вместе с адресованными по цепочке, располагаются в каталогах ПО Oracle в разных архивах ORACLEHOME).
Два последние класса позволяют работать с электронным бумажником Oracle посредством командной строки, а первый - посредством графики; он и назначен быть основным инструментом для пользователя. Описания API, позволяющего пользователю работать с бумажником из своей программы, фирма Oracle не дает.
Бумажник не обязательно открывать и закрывать всякий раз по мере надобности вручную. На компьютере, где он располагается, можно сообщить ему режим «автооткрытия» - при запуске ОС. Сделать это можно опять-таки через Oracle Wallet Manager:
Обратите внимание, что после этого в каталоге бумажника на пару файлу ewallet.p12 появился файл cwallet.sso. Расширение sso есть сокращение от single sign-on, обозначающего «технику единого входа». Новый файл есть по сути копия прежнего бумажника (но не копия файла).
Упражнение. Проверить автоматическую готовность бумажника к употреблению после перевода в режим автооткрытия.
Чтобы снять режим автооткрытия, в том же меню Wallet следует снять пометку Auto Logon. Файл cwallet.sso после этого автоматически пропадет. Это же (но не обратное !) действие можно выполнить командой, например: >mkstore -wrl C:\oracle\admin\orcl\wallet -deleteSSO
Внешнее хранение ключа
Бумажник Oracle позволяет работать с ключами, хранимыми не в файле, а на внешнем устройстве, например подключаемом через порт USB. В этом случае (де-)шифрующие процедуры отрабатываются также на внешнем устройстве. Связь с таким устройством позволяет организовать программа orapki, однако она носит вполне конкретный характер и здесь не поясняется.
В Windows есть возможность поместить бумажник не в файл, а в реестр. Местонахождением в этом случае будет раздел \\HKEY_CURRENT_USER\SOFTWARE\ORACLE\WALLETS, волей-неволей скрывающий бумажник в профиле пользователя; то есть сохранение его в реестре выгоднее и по части управляемости, и по части защищенности.
Перенести бумажник в реестр можно средствами Oracle Wallet Manager (пометка Use Windows Registry в меню Wallet):
Создать бумажник с главным ключом шифрования можно неявно командой ALTER SYSTEM SET ENCRYPTION WALLET ... или явно программами Oracle Wallet Manager и mkstore. Обратите внимание, что главный ключ (симметричный) будет применяться СУБД для шифрования данных при размещении на диске и расшифровке при взятии с диска, поэтому дальнейшая работа предполагается на сервере, с серверным ПО.
К сожалению, для электронного бумажника в Oracle ПО написано недостаточно тщательно, так что несоблюдение описанного далее порядка действий способно привести вплоть до ошибки ORA-00600 и необходимости перезагрузки СУБД.
Проще завести бумажник неявно, командой SQL. Для этого нужно создать необходимый умолчательный каталог и выдать команду SQL от имени SYS, например в SQL*Plus: SQL> HOST mkdir C:\oracle\admin\orcl\wallet SQL> ALTER SYSTEM SET ENCRYPTION KEY IDENTIFIED BY "amicus123";
Приведенный пароль будет служить для последующего открытия бумажника и вообще доступа к его содержимому. Двойные кавычки неслучайны, так как в пароле различаются большие и малые буквы. Кроме того пароль должен содержать более 8 символов и складываться одновременно из букв и цифр. Для смены пароля в будущем надо будет использовать программу Oracle Wallet Manager, обратиться к которой в Windows можно через меню запуска программ или из командной строки ОС, а в Unix - набором owm в командной строке ОС.
По указанной команде SQL в (умолчательном) каталоге появится файл бумажника с главным ключом доступа. К фактическому использованию главного ключа из бумажника мы еще не готовы, так как бумажник нужно открыть. Команды открытия и закрытия бумажника: ALTER SYSTEM SET ENCRYPTION WALLET OPEN AUTHENTICATED BY "amicus123"; ALTER SYSTEM SET ENCRYPTION WALLET CLOSE;
Выполним первую команду, и созданый предварительно бумажник можно использовать.
Данные БД могут находиться на внешнем носителе и в виде запасных (резервных) копий. Версия 10 позволила их шифровать. Это делается программой rman, и распространяется на резервные наборы (но не на копии образов файлов).
Шифрование резервного набора программой rman может осуществляться (1) с явным указанием ключа шифрования; (2) «прозрачно», то есть без явного указания, когда ключ берется из бумажника; (3) в «двойном режиме», когда допускается указывать ключ явно или пользоваться бумажником - по выбору. Администратору проще использовать для шифрования резервных наборов бумажник, и этот способ рассмотрен ниже.
Выдадим: >rman TARGET / ... [ответ] ... RMAN> SET ENCRYPTION OFF; ... [ответ] ... RMAN> BACKUP AS BACKUPSET TABLESPACE users TAG "unencrypted"; ... [ответ] ... RMAN> SET ENCRYPTION ON; ... [ответ] ... RMAN> BACKUP AS BACKUPSET TABLESPACE users TAG "the last one"; ... [ответ] ...
Для проверки можно последовательно выдать команды (далее в этом разделе - все для rman):
RESTORE TABLESPACE users VALIDATE; SQL "ALTER SYSTEM SET ENCRYPTION WALLET CLOSE"; RESTORE TABLESPACE users VALIDATE; RESTORE TABLESPACE users FROM TAG "unencrypted" VALIDATE; SQL 'ALTER SYSTEM SET ENCRYPTION WALLET open AUTHENTICATED BY "amicus12 3"'; RESTORE TABLESPACE users VALIDATE;
Алгоритмы, которые можно использовать для шифрования, перечисленны в таблице V $RMAN_ENCRYPTION_ALGORITHMS. Задать нужный алгоритм можно явочным путем, например: SET ENCRYPTION ALGORITHM 'AES192';
На практике в rman удобно установить умолчания, например: CONFIGURE ENCRYPTION ALGORITHM 'AES256'; CONFIGURE ENCRYPTION FOR DATABASE ON;
Создадим таблицу для работы, для определенности в схеме SCOTT: CREATE TABLEclosed ( a VARCHAR2 ( 10 ) , b VARCHAR2 ( 10 ) , c VARCHAR2 ( 10 ) ); INSERT INTO closed VALUES ( 'normal1', 'secret', 'normal1' ); INSERT INTO closed VALUES ( 'normal2', 'secret', 'normal2' ); COMMIT;
Для начала рассмотрим обычное хранение строк. Выдадим в SQL*Plus: SQL> SELECT 2 DBMS_ROWID.ROWID_RELATIVE_FNO ( ROWID ) file# 3 , DBMS_ROWID.ROWID_BLOCK_NUMBER ( ROWID ) block# 4 FROM closed SQL> ;
FILE# BLOCK# ---------- ---------- 4 4
597 597
Обе короткие строки попали в один блок на диске. В моем случае это блок № 597 в файле № 4. Подставим полученные значения в команду, которую выдадим от имени SYS: ALTER SYSTEM DUMP DATAFILE 4 BLOCK 597;
В трассировочном файле серверного процесса, обслуживающего сеанс, появилась примерно следующая информация: ... EEF7DB0 32656662 5F353633 72756F53 6F546563 [bfe2365_SourceTo] EEF7DC0 4C4D5448 766E6F43 0703012C 6D726F6E [HTMLConv,...norm] EEF7DD0 06326C61 72636573 6E077465 616D726F [al2.secret.norma] EEF7DE0 012C326C 6F6E0703 6C616D72 65730631 [l2,...normal1.se] EEF7DF0 74657263 726F6E07 316C616D A1810604 [cret.normal1....] Block header dump: 0x01000255 ...
Пока еще не засекреченные значения выделены серым фоном. Зашифруем их в блоке: ALTER TABLE closed MODIFY ( b ENCRYPT );
Это можно сделать только при открытом бумажнике. Вот что получим в файле трассировки серверного процесса: ... EEF7D30 0B6A7807 12380B13 0703022C 6D726F6E [.xj...8.,...norm] EEF7D40 34326C61 0E8464A4 1304CAAE E1116635 [al24.d......5f..] EEF7D50 5B06C8CD C3AABA4A 8B4EA144 CE2B4987 [...[J...D.N..I+.] EEF7D60 EB2DEBB1 E97EB0C5 CDCA2CDB 99AC18E9 [..-...~..,......] EEF7D70 52E1F415 CA85201C 726F6E07 326C616D [...R. ...normal2] EEF7D80 0703022C 6D726F6E 34316C61 1F21C866 [,...normal14f.!.] EEF7D90 D765D462 EC2D8A33 8DF8F328 EC42E142 [b.e.3.-.(...B.B.] EEF7DA0 CB3EEB72 A36909CE A28C845E 0F04567C [r.>...i.^...|V..] EEF7DB0 3C74BEC5 8F3EAEA8 B3612F6E 6009C40C [..t.n/a....`] EEF7DC0 726F6E07 316C616D 0703002C 6D726F6E [.normal1,...norm] EEF7DD0 06326C61 72636573 6E077465 616D726F [al2.secret.norma] EEF7DE0 002C326C 6F6E0703 6C616D72 65730631 [l2,...normal1.se] EEF7DF0 74657263 726F6E07 316C616D A9BB0601 [cret.normal1....] Block header dump: 0x01000255 ...
Когда возникает надобность шифровать данные многих столбцов в многих таблицах, приходится иметь дело с большим количеством справочных сведений, что технологически хлопотно. Версия 11 дает для таких случаев обобщенное решение: шифрование всех данных, помещаемых в конкретное табличное пространство. Такое свойство табличного пространства неизменно и указывается один раз при его создании, например: CREATE TABLESPACE encrypted_data DATAFILE 'G:\oracle\oradata\orcl\encrypt_df.dat' SIZE 1M ENCRYPTION USING '3DES168' DEFAULT STORAGE ( ENCRYPT ) ;
Оно отображено в поле ENCRYPTED таблицы DBATABLESPACES.
Посмотреть состояние и местонахождение бумажника с шифроключами можно только с версии 11 в таблице V$ENCRYPTION_WALLET.
Перечень шифруемых столбцов в таблицах БД можно получить из отдельных системных таблиц DBA/ALL/USER_ENCRYPTED_COLUMNS. В нашем случае мы получим: SQL> SELECT * FROM user_encrypted_columns;
TABLE_NAME COLUMN_NAME ENCRYPTION_ALG SAL ------------------- ------------------- -------------------------- --- CLOSED B AES 192 bits key NO
Полное имя последнего столбца SALT. Поле ENCRYPTIONALG сообщает алгоритм шифрования. Кроме умолчательного AES192 возможны AES128, AES256 и 3DES168. Эти алгоритмы следует указывать явно: ALTER TABLE closed REKEY USING 'aes256';
Обратите внимание, что алгоритм указывается не для столбца, а для всей таблицы. Это потому, что Oracle не позволяет разным столбцам таблицы использовать разные алгоритмы шифрования: технически «шифрование выполняется на уровне блока» (цитата). Фактически последняя команда сменяет не только алгоритм, но и ключ шифрования, тоже один на всю таблицу. Этот собственный ключ шифрования таблицы (не «главный») тут же сам шифруется главным ключом из бумажника и запоминается для нее в БД, в системной таблице ENC$. Оттуда он будет браться при всякой шифровке/расшифровке значений полей строк таблицы. Так, при обращении к зашифрованному полю таблицы СУБД возьмет из ENC$ зашифрованый ключ этой таблицы, расшифрует его главным ключом из бумажника, и уже восстановленым ключом таблицы расшифрует значение поля.
Если нужно сменить хранимые шифрозначения, можно выдать просто: ALTER TABLE closed REKEY;
На «законную» возможность читать данные это никак не скажется (равно как и предыдущее действие), но хранимые значения будут подменены на вычисленные заново.
Упражнение. Проверить, изменится ли хранение в БД зашифрованных данных при смене шифроключа таблицы.
Посмотреть ключи шифрования в бумажнике можно программой mkstore, например: >mkstore -wrl C:\oracle\admin\orcl\wallet -list
Файл бумажника ewallet.p12 имеет право располагаться в любом месте файловой системы сервера, лишь бы только в области доступности СУБД. Нестандартное его местонахождение следует указать в конфигурационном файле серверного сетевого ПО sqlnet.ora. Включим в него параметр: WALLET_LOCATION =
( SOURCE = ( METHOD = FILE ) ( METHOD_DATA = ( DIRECTORY = C:\oracle\product\10.2.0\db_1\encryptionwallet ) ) )
Создадим указанный каталог и перенесем в него ранее созданый файл ewallet.p12. Закроем бумажник и откроем снова командами ALTER SYSTEM, как выше. Файл бумажника самодостаточен, и поэтому сделанного довольно, чтобы продолжать с ним работу на новом месте.
Вместо названия WALLETLOCATION файл sqlnet.ora понимает название ENCRYPTIONWALLETLOCATION.
Термин «прозрачное шифрование данных» (TDE) используется для обозначения процессов автоматической шифровки данных при размещении на носитель и дешифровки при чтении с носителя. «Прозрачное» здесь означает «прозрачное» для прикладной программы, в которой ни коим образом нет нужды учитывать фактическое выполнение указанных действий. В противовес этому программа имеет право самостоятельно шифровать нужные значения прежде чем передавать их БД и самостоятельно расшифровывать по извлечению, пользуясь, например, пакетом DBMSCRYPTO. Оба подхода имеют свои достоинства; при этом TDE проще для программиста, но и требует бумажника.
Техника TDE не присуща исключительно СУБД Oracle (пример: SQL Server), или даже базам данных вообще (пример: патент IBM).
Рассматривается использование электронного бумажника Oracle Wallet для установления защищенных соединений СУБД с узлами интернета по протоколу TCPS и клиентских программ с СУБД по протоколу HTTPS.
Преподаватель технологий Oracle
http://open.oracle.tu2.ru/.index
Декабрь 2008 г.
Небольшая правка: январь 2009 г.
И начал меня спрашивать: «Что за человек? Откудова?»
И я сказал, что с Москвы, да и подал ему господарский лист воложской.
Московского священника Ивана Лукьянова хождение в Святую землю
Правка файла tnsnames.ora может выглядеть примерно так: ... ORCL_SSL = ( DESCRIPTION = ( ADDRESS = ( PROTOCOL = TCPS )( HOST = oraserver )( PORT = 2484 ) ) ( CONNECT_DATA = ( SERVICE_NAME = orcl ) ) ) ...
(Предполагается, что имя службы БД - orcl).
Правка файла sqlnet.ora может выглядеть примерно так: ... NAMES.DIRECTORY_PATH = ( TNSNAMES )
SSL_VERSION = 3.0
WALLET_LOCATION = ( SOURCE = ( METHOD = FILE ) ( METHOD_DATA = ( DIRECTORY = C:\oracle\product\10.2.0\client_1\NETWORK\wallet ) ) ) ...
Примерный фрагмент из listener.ora может выглядеть так: ... LISTENER = ( DESCRIPTION_LIST = ( DESCRIPTION = ( ADDRESS = ( PROTOCOL = TCP )( HOST = oraserver )( PORT = 1521 ) ) ( ADDRESS = ( PROTOCOL = TCPS )( HOST = oraserver )( PORT = 2484 ) ) ) )
SSL_CLIENT_AUTHENTICATION = FALSE
SQLNET.AUTHENTICATION_SERVICES = ( TCPS, NTS )
WALLET_LOCATION = ( SOURCE = ( METHOD = FILE ) ( METHOD DATA = ( DIRECTORY = C:\oracle\product\10.2.0\db_1\NETWORK\wallet ) ) ) ...
После подобной правки файла listener.ora программу listener стоит перезапустить. Правка файла sqlnet.ora может выглядеть примерно так: ... SQLNET.AUTHENTICATION_SERVICES = ( TCPS, NTS )
SSL_CLIENT_AUTHENTICATION = FALSE
SSL_VERSION = 3.0
WALLET_LOCATION = ( SOURCE = ( METHOD = FILE ) ( METHOD_DATA = ( DIRECTORY = C:\oracle\product\10.2.0\db_1\NETWORK\wallet ) ) ) ...
Нагляднее импортировать сертификаты опять-таки в Oracle Wallet Manager, хотя делать это можно и программами из командной строки.
При желании можно с пощью меню запомнить текст заявки во внешнем файле.
Вначале импортируется корневой сертификат. Используется меню Operations —»Import Trusted Certificate.
Во вторую очередь импортируется сертификат пользователя посредством меню Operations — Import User Certificate. Оба действия допускают указание как ссылки на файл, так и живого текста.
В результате ветка Certificate (Requested) объектов бумажника получит вид Certificate (Ready):
Сертификаты импортируются отдельно в бумажники сервера и клиента.
Процесс установки соединеий клиентов с СУБД listener должен быть настроен на прием заявок подключений по протоколу TCPS. Для этого в файле listener.ora следует пополнить описание списка портов в параметре LISTENER. По умолчанию Oracle Net использует для TCPS порт 2484; ниже эта традиция сохранена. Указание SSLVERSION в файлах ниже приводится для определенности и не имеет принципиального значения.
Выставить требуемые значения параметрам можно программой Net Manager, например:
Может случиться, что ПО Advanced Security доустанавливалось впоследствии. Из-за внутренних ошибок программа Net Manager не всегда в таких случаях способна показать позицию Oracle Advanced Security ниспадающего меню. Выйти из положения можно, подправив строку из файла netproperties в каталоге %ORACLE_HOME%\network\tools; например заменить: INSTALLEDCOMPONENTS=CLIENT,ORACLENET
на: INSTALLEDCOMPONENTS=CLIENT,ORACLENET,ANO.
(ANO - сокращение старого названия нынешнего ПО Advanced Security Option).
Наличие бумажника с необходимым сертификатом позволяет устанавливать соединения СУБД с узлами сети по защищенному протоколу HTTPS с помощью пакета UTLHTTP. Для примера рассмотрим адрес . Чтобы обратиться к нему из программы потребуется занести в бумажник сертификат. Сертификат можно извлечь из полученного ранее файла thawte-roots.zip, из каталога Thawte Server Roots. С равным успехом для импорта в бумажник годятся и двоичный файл ThawtePremiumServerCA.cer и содержимое текстового ThawtePremiumServerCA_b64.txt. Импортируем сертификат как и выше, с помощью Wallet Manager и меню Operations — Import Trusted Certificate.
Подготовим текст программы для SQL*Plus: SET SERVEROUTPUT ON
DECLARE req UTL_; resp UTL_; walletdir VARCHAR2 ( 100 ) := 'file:C:\oracle\product\10.2.0\db_1\NETWORK\wallet'; walletpass VARCHAR2 ( 100 ) := 'amicus123';
targeturl VARCHAR2 ( 100 ) := 'https://www.thawte.com';
BEGIN UTL_HTTP.SET_WALLET ( walletdir, walletpass ); req := UTL_HTTP.BEGIN_REQUEST ( targeturl ); resp := UTL_HTTP.GET_RESPONSE ( req ); UTL_HTTP.END_RESPONSE ( resp );
DBMS_OUTPUT.PUT_LINE ( 'HTTP response status code: ' resp.status_code ); DBMS_OUTPUT.PUT_LINE ( 'HTTP response reason: ' resp.reason phrase ); END; /
При наличии приближенного сервера (proxy) потребуется связаться через него (UTL_HTTP.SET_PROXY).
Прогон текста должен дать результат: HTTP response status code: 200
HTTP response reason: OK
Упражнение. Убрать из текста программы обращение к бумажнику (SETWALLET) и проверить доступ к адресам: (а) , (б) .
В созданом средствами Oracle бумажнике имеется несколько предустановленных сертификатов. Один из них готов для установления прямого защищенного соединения по протоколу HTTPS с узлом по адресу .
Получение сертификата пользователя производится по подготовленной заявке (request). Подготовить заявку можно с помощью Wallet Manager, отдельно для бумажников на сервере и на клиенте. Обратиться к форме составления заявки можно через меню Operations ® Add Certificate Request. В форме Create Certificate Request следует выбрать Key Size = 1024 и нажать кнопку Advanced. В появившуюся форму нужно внести различительное имя и нажать OK:
Если теперь «встать» на ветку Certificate (Requested) дерева объектов бумажника, справа увидим текст заявки на сертификат:
Для установления защищенного соединения по SSL потребуется получить цифровые сертификаты подлинности: (а) «пользователя» и (б) «корневой». Сертификат пользователя будем получать на обращение к ресурсу, обозначенному следующим «различительным именем» (distinguished name, dn): cn=orcl, cn=OracleContext, dc=us, dc=oracle, dc=com
(Предполагается, что имя экземпляра СУБД - orcl). Правила построения различительных имен многократно описаны в литературе и в интернете.
Корневой сертификат понадобится для того, чтобы подтвердить сертификат пользователя. Подтвержденя ему не требуется, так как он подтверждает сам себя (отсюда название).
Получить сертификат можно разными способами:
от уполномоченных центров сертификации (certificate authority, CA), выдающих сертификаты за плату; с помощью бесплатных программ получения сертификатов, например openSSL;
от собственного уполномоченного центра в рамках Identity Management Infrastructure в составе Oracle Application Server.
Последний вариант выглядит естественным при работе с ПО Oracle, однако, как и второй, требует определенного разбирательства, отвлекающего от основного изложения. Простым выходом может оказаться получение пробного бесплатного сертификата с трехнедельным сроком годности от фирмы thawte.
На месте в web нужно найти страницу «21-Day Free Trial SSL Certificate from thawte» и заполнить поля своими данными. Далее на странице «21-Day Free SSL Trial Certificate)) нужно проставить отметку SSL123 Certificate (All servers) и в поле для заявки внести текст, полученный от Wallet Manager. Нажав next, получим в ответ текст сертификата. Пока его нужно запомнить в каком-нибудь файле, например userCert.txt. Такой файл получаем отдельно для бумажника на сервере и на клиенте.
Корневой сертификат можно получить по адресу . Скачав файл thawte-roots.zip, нужно извлечь из него текстовое или двоичное представление корневого сертификата в каталоге Thawte Test Roots.
ПО Oracle позволяет создать пустой бумажник, и потом включить в него необходимые сертификаты подлинности. Однако программы owm (Wallet Manager), orapki, mkstore и mkwallet позволяют создать бумажник с некоторым начальным набором сертификатов. Первая из этих программ сумеет создать желаемый каталог для хранения файла бумажника сама, а остальные предполагают каталог уже имеющимся. Пример, для сервера: >set WALLETLOC=C:\oracle\product\10.2.0\db_1\NETWORK\wallet >mkdir %WALLETLOC% >mkstore -wrl %WALLETLOC% -create
В диалоге потребуется указать придуманный пароль, например, по-прежнему amicus123. Заметьте, что в созданом каталоге образовались сразу два файла, что соответствует постоянно открытому бумажнику; это-то нам и требуется.
Еще пример создания: >orapki wallet create -wallet %WALLETLOC% -pwd amicus123
Появился один файл ewallet.p12, но зато этой же программой можно ознакомиться с его содержимым: >orapki wallet display -wallet %WALLETLOC% -pwd amicus123
Наконец, создать бумажник и работать с его содержимым можно через Oracle Wallet Manager (меню Wallet ® New). При этом от следующего предложения придется отказаться:
В противном случае программа предложит текст заявки на получение сертификата, что пока не нужно. Свойство бумажника Auto Login в Wallet Manager нужно будет задать самостоятельно.
Следует обратить внимание, чтобы места нахождения файлов бумажников были доступны элементам ПО соответственно сервера и клиента.
На клиенте набираем: >sqlplus scott/tiger@orcl_ssl
Убедиться, что действительно произошло соединение по SSL, можно по файлам протокола (журнала) соединений listener.log. Если же включить трассировку сеанса (параметр TRACE_LEVEL_CLIENT в файле sqlnet.ora), увидим в файле трассировки примерно следующий фрагмент: [10-DEC-2008 20:13:11:828] nzos_Trace_Negotiated_Cipher: The Final Negotiated SSL Cipher Suite is: SSL_RSA_WITH_3DES_EDE_CBC_SHA
[10-DEC-2008 20:13:11:828] ntzdosecneg: SSL handshake done
Вторая активная область использования электронного бумажника Oracle - поддержка защищенных соединений между СУБД и узлами интернет. Защита соединений между участниками интернет строится на использовании шифрования передаваемых данных, обычно по схеме публичной инфраструктуры ключей (PKI), а это требует передачи от одного участника к другому шифроключа. Риск постороннего вмешательства в такую передачу значительно выше, чем при обращении СУБД к локальной файловой системе, так что кроме собственно шифроключа участники передают друг другу еще специальное подтверждение подлинности, то есть «цифровой сертификат» (), дающий принимающей стороне уверенность, что шифр не подложный. Бумажник Oracle способен такие сертификаты хранить.
Соединения участников сети могут быть двух типов: СУБД с другими участниками, когда она выступает в качестве клиента, и других участников (клиентских программ) с СУБД. Ниже приводятся примеры организации того и другого.
ПО Oracle Advanced Security позволяет проводить авторизацию соединений клиента с сервером средствами сторонних продуктов, таких как Kerberos или RADIUS. Здесь же будет показано, как это можно сделать с использованием бумажника и техники защищенного соединения SSL (более современное название - TLS, ). С SSL связано и иное решение: соединяться в Oracle без Advanced Security, но по каналу связи («туннелю») SSL в ОС. Оно здесь не рассматривается по меньшей мере потому, что лишает смысла тему настоящей статьи.
>ftp
ftp> open localhost 2100
Connected to FLEXIT-V3TNTGIS. 220- FLEXIT-V3TNTGIS Unauthorised use of this FTP server is prohibited and may be subject to civil and criminal prosecution. 220 FLEXIT-V3TNTGIS FTP Server (Oracle XML DB/Oracle Database) ready. User (FLEXIT-V3TNTGIS:(none)): xdb
331 pass required for XDB Password: 230 XDB logged in ftp> ls
200 PORT Command successful 150 ASCII Data Connection home public sys xdbconfig.xml 226 ASCII Transfer Complete ftp: 34 bytes received in 0,39Seconds 0,09Kbytes/sec. ftp> get xdbconfig.xml
200 PORT Command successful 150 ASCII Data Connection 226 ASCII Transfer Complete ftp: 11612 bytes received in 0,61Seconds 19,07Kbytes/sec. ftp> bye
221 QUIT Goodbye.
Жирным шрифтом выделены команды, набранные пользователем (набор пароля для пользователя XDB на экране не отразился). По результату этих действий из репозитария XML DB в текущий каталог ОС скопировался файл xdbconfig.xml. Подключиться по FTP к репозитарию XML DB можно было и под любым другим именем пользователя Oracle, однако не все пользователи смогут совершать все операции с имеющимися файлами.
Упражнение:
Проверить появление в текущем каталоге ОС файла xdbconfig.xml. Подключиться по FTP под именем SCOTT и удостовериться в невозможности извлечь файл из XML DB.
XML DB представляет собой набор средств и возможностей СУБД и БД в Oracle, ориентированный на работу с форматом XML как по части преобразования, так и хранения данных. Для изначально таблично-организованной базы данных XML DB открывает новый способ хранения и употребления данных, сочетающийся с табличным. В этой статье рассматриваются темы установки XML DB в существующую БД и организации внешнего доступа. В последующих статьях будут показано, какие возможности дает установленная XML DB.
Войти в браузер MS IE, набрать в поле адреса следующие варианты и проверить работу:
Во-первых, требуется удостовериться в нужных значениях параметров СУБД DISPATCHERS (обязательно) и LOCAL_LISTENER (при наличии нескольких процессов listener). Установка нужных значений может быть выполнена так:
ALTER SYSTEM SET dispatchers = '(PROTOCOL=TCP)(SERVICE=ORCLXDB)' SCOPE = SPFILE ;
ALTER SYSTEM SET local_listener = '(ADDRESS=(PROTOCOL=TCP)(HOST=localhost)(PORT=1521))' ;
При этом указываемое значение SERVICE формируется как имя_СУБДXDB (здесь считается, что INSTANCE_NAME = ORCL), а значения HOST и PORT соответствуют местонахождению и месту приписки процесса listener (когда этих процессов несколько - того, что будет обслуживать доступ через HTTP). В работе, получив заявку на соединение с XML DB, процесс listener передаст ее дистпетчеру, а тот - одному из общественных (shared) серверных процессов.
Во-вторых, требуется назначить или переназначить (при необходимости) порты для публичного доступа по HTTP и FTP. Порты по умолчанию соответственно 8080 и 2100, однако, начиная с версии 10.2, они изначально выставлены в 0. Для переустановки (а с версии 10.2 - для установки) требуется выполнить от имени SYS:
EXECUTE DBMS_XDB.SETFTPPORT ( 2100 ) EXECUTE DBMS_XDB.SETHTTPPORT ( 8080 ) ALTER SYSTEM REGISTER;
Выдача последней команды некритична. После этого по некоторым рекомендациям нужно перезапустить СУБД:
SQL> SHUTDOWN IMMEDIATE SQL> STARTUP
В ОС следует выдать:
>lsnrctl status
Ожидаемый результат должен выглядеть примерно так:
... Listening Endpoints Summary... (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(PIPENAME=\\.\pipe\EXTPROC1ipc))) (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=FLEXIT-V3TNTGIS)(PORT=1521))) (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=FLEXIT-V3TNTGIS)(PORT=8080))(Presentation=HTTP)(Session=RAW)) (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=FLEXIT-V3TNTGIS)(PORT=2100))(Presentation=FTP)(Session=RAW)) Services Summary... Service "PLSExtProc" has 1 instance(s). Instance "PLSExtProc", status UNKNOWN, has 1 handler(s) for this service... Service "orcl" has 1 instance(s). Instance "orcl", status READY, has 1 handler(s) for this service... Service "orclXDB" has 1 instance(s). Instance "orcl", status READY, has 1 handler(s) for this service... ...
В версии 10.2 появится также информация о службе имя_СУБД_XPT. При желании ее можно отключить скрытым параметром СУБД, однако ж и ее наличие не мешает обычной работе.
Результатом заведения XML DB в базе явилось появление в ее составе так называемого репозитария XML DB, фактически - файловой системы. Для работы с репозитарием извне возможно и удобно открыть доступ по протоколам HTTP и FTP.
При установленном доступе по HTTP, Oracle поддерживает также основанное на этом протоколе средство WebDAV (Web-based Distributed Authoring and Versioning, http://techinfo.net.ru/webdav.html). ОС Windows обеспечивает клиентский доступ к серверу WebDAV, позволяя обращаться к репозитарию XML DB как к каталогу собственной файловой системы.
Подключиться в Windows Explorer к сетевому ресурсу с именем 'XML DB Repository' и копировать файлы между репозитарием XML DB и файловой системой ОС методом Drag and Drop.
Доступ по WebDAV обеспечивает не обязательно только Windows Explorer, но и целый ряд продуктов разных фирм.
Проверка доступа к репозитарию- возможно наиболее эффектный шаг в освоении XML DB. Для FTP может выполняться двояко.
Войти в браузер Web, набрать в поле адреса следующие варианты и проверить работу:
http://localhost:8080/
http://localhost:8080/sys/schemas/OE/localhost:8080/source/schemas/poSource/xsd/
http://localhost:8080/sys/schemas/OE/localhost:8080
/source/schemas/poSource/xsd/purchaseOrder.xsd
Обратите внимание на доступность текстового вида страниц.
Мура туфельку снимала, В огороде закопала: - Расти, туфелька моя, Расти, маленькая ! |
Корней Чуковский, Что сделала Мура, когда ей прочли сказку "Чудо-дерево" |
Установка XML DB может выполняться средствами Database Configuration Assistant (DBCA), либо вручную. Типовой вариант БД, начиная с версии 9.2, включает предустановленную XML DB и не требует дополнительной установки.
Узнать о наличии установленной XML DB и готовности к работе можно так:
SQL> CONNECT / AS SYSDBA Connected. SQL> SELECT count ( * ) 2 FROM dba_objects 3 WHERE owner = 'XDB' AND status = 'INVALID';
COUNT(*) ---------- 0
SQL> COLUMN comp_name FORMAT A30 SQL> SELECT comp_name, status, version 2 FROM dba_registry 3 WHERE comp_name = 'Oracle XML Database';
COMP_NAME STATUS VERSION ------------------------------ ----------- ------------ Oracle XML Database VALID 10.2.0.1.0
При полученных выше ответах может потребоваться, однако, разблокировать подключение к СУБД (уже имеющемуся) пользователю XDB, например:
ALTER USER xdb ACCOUNT UNLOCK IDENTIFIED BY xdb;
Если же в существующей БД XML DB не установлена, вручную это можно сделать следующей последовательностью действий от имени SYS:
Завести табличное пространство для нужд пользователя XDB (желательно). Прогнать сценарий catqm.sql заведения необходимой инфраструктуры в БД (реестр XML DB, служебные пакеты PL/SQL и пр.):
SQL> @?/rdbms/admin/catqm пароль_для_XDB табличное_пространство_для_XDB табличное_пространство_для_временных данных_XDB
Прогнать сценарий catqm.sql заведения необходимых библиотек на Java и типов (они могут иметься и без этого):
SQL> @?/rdbms/admin/catxdbj
Прогнать сценарий создания пакетов из состава XDK (по желанию):
SQL> @?/rdbms/admin/initxml
Выполнить SHUTDOWN и STARTUP.
Для убирания из БД XML DB достаточно выполнить от имени SYS:
SQL> @?/rdbms/admin/catnoqm
SHUTDOWN и STARTUP
Пользователь XDB и сопутствующие пакеты будут удалены.
Преподаватель технологий Oracle
... К несчастию, никак не мог прибрать рифмы для лядунок и киверов; итак, пусть будет это в прозе. |
А. С. Грибоедов, Письмо из Бреста Литовского к издателю «Вестника Европы» |
Действия в Windows:
Открываем форму My Network Places. Это пожно сделать через Internet Explorer или через форму Network Connections в установках компьютера. Открываем форму Add a network place. Входим в помошник установки (wizard) Выбираем Choose another network connect. Вводим адрес http://localhost:8080/. В появившемся окошке вводим имя и пароль пользователя Oracle, например xdb/xdb. Указываем имя сетевого соединения, например: XML DB Repository. Снимаем «галочку» с позиции выбора Open this network place … (необязательно) и нажимаем Finish.
Соединение заведено. Войти в репозитарий можно, нажав дважны на имя «каталога» XML DB Repository.
Установленная в БД XML DB позволяет регистрировать в базе схемы XML, задающие типы документов XML. Зарегистрированная в репозитарии схема может употребляться для данных типа XMLTYPE: как хранимых в обычных таблицах, так и доступных из производных (синтезированных) таблиц типа XMLTYPE. В статье показано на примерах, как это делать.
Просто указанный XMLTYPE требует лишь, чтобы помещаемый в БД документ был правильно оформлен. Зарегистрированная в XML DB схема XML позволяет указать для размещаемых в конкретные поля документов XML-образные ограничения целостности, позволяя хранить только «годные» (valid) из них.
Создадим таблицу объектов XMLTYPE, уточненную ссылкой на зарегистрированную схему:
CREATE TABLE xtbooks OF XMLTYPE XMLSCHEMA "http://localhost:8080/public/bookCover.xsd" ELEMENT "cover" ;
Проверка занесения данных:
INSERT INTO xtbooks VALUES ( XMLTYPE ( '<cover><author>Einstein</author></cover>' ) );
INSERT INTO xtbooks VALUES ( XMLTYPE ( ' <cover> <title>Java Programming with Oracle JDBC</title> <author>Donald Bales</author> <publisher>OReilly and Associates</publisher> <pubdate>December 2001</pubdate> <isbn>0-596-00088-x</isbn> <pages>496</pages> </cover> ' ) );
COMMIT;
Упражнение. Проверьте реакцию СУБД на попытку вставить в таблицу XTBOOKS правильно оформленный документ XML, не соответствующий описанию схемы.
Аналогично накладываются дополнительные ограничения на данные столбца XMLTYPE в обычной таблице:
CREATE TABLE tbooks ( id NUMBER ( 9 ) , description XMLTYPE ) XMLTYPE description STORE AS OBJECT RELATIONAL XMLSCHEMA "http://localhost:8080/public/bookCover.xsd" ELEMENT "cover" ;
В приведенных примерах данные в БД фактически будут храниться «объектно-реляционно», то есть будучи распределены по разным структурам БД, в том числе по спрятанным столбцам таблиц. Однако типизируя таблицу или столбец типа XMLTYPE схемой, можно потребовать фактического хранения документа в виде объекта CLOB, подобно тому, как это происходит при отсутствии типизации схемой.
Пример:
CREATE TABLE xtbooksclob OF XMLTYPE XMLTYPE STORE AS CLOB
XMLSCHEMA "http://localhost:8080/public/bookCover.xsd" ELEMENT "cover" ;
Упражнение. Проверить возникновение новых объектов БД и их структуры по результатам заведения таблиц XTBOOKS, TBOOKS и XTBOOKSCLOB. Воспользоваться для этого таблицами USER_OBJECTS, USER_TAB_COLS, USER_TYPES, USER_TRIGGERS, USER_LOBS.
При отсутствии XML DB не заперщено создавать производную таблицу (view), выдающую данные в виде таблицы документов XML (типа XMLTYPE) на основе данных из обычных таблиц. Рассмотрим, как при наличии XML DB можно дополнительно уточнить такую производную таблицу схемой XML.
В этом примере регистрируется схема, не взятая из ресурса репозитария, как ранее, а явно выписанная в виде текста XML:
BEGIN DBMS_XMLSCHEMA.REGISTERSCHEMA ( schemaurl => 'http://localhost:8080/public/employee.xsd'
, schemadoc => '<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:element name="employee"> <xs:complexType> <xs:sequence> <xs:element name="ename" type="xs:string"/> <xs:element name="job" type="xs:string"/> <xs:element name="sal" type="xs:integer"/> </xs:sequence> <xs:attribute name="empno" type="xs:integer"/> </xs:complexType> </xs:element> </xs:schema> ' ); END; /
Пример создания производной таблицы:
CREATE OR REPLACE VIEW empxml_schema_view OF XMLTYPE XMLSCHEMA "http://localhost:8080/public/employee.xsd" ELEMENT "employee" WITH OBJECT ID ( EXTRACT ( SYS_NC_ROWINFO$, '/employee/@empno' ).GETNUMBERVAL ( ) ) AS SELECT XMLELEMENT ( "employee" , XMLATTRIBUTES ( e.empno AS "empno" ) , XMLFOREST ( e.ename AS "ename", e.job AS "job", e.sal AS "sal" ) ) FROM emp e ;
Наличие данных, противоречащих схеме, не препятствует извлечению данных результата при обращении к созданой производной таблице. Однако ж имеется метод, способный выполнить проверку соответствия схеме:
SELECT VALUE ( v ).ISSCHEMAVALID ( ) FROM empxml_schema_view v;
Упражнение. Создать производную таблицу EMLXML_VIEW по аналогии с EMLXML_SCHEMA_VIEW, не уточненной схемой (для этого потребуется удалить из определения выше две строки, выделенные жирным шрифтом). Выполнить следующие проверки:
Просто указанный XMLTYPE требует лишь, чтобы помещаемый в БД документ был правильно оформлен. Зарегистрированная в XML DB схема XML позволяет указать для размещаемых в конкретные поля документов XML-образные ограничения целостности, позволяя хранить только «годные» (valid) из них.
Создадим таблицу объектов XMLTYPE, уточненную ссылкой на зарегистрированную схему:
CREATE TABLE xtbooks OF XMLTYPE XMLSCHEMA "http://localhost:8080/public/bookCover.xsd" ELEMENT "cover" ;
Проверка занесения данных:
INSERT INTO xtbooks VALUES ( XMLTYPE ( '<cover><author>Einstein</author></cover>' ) );
INSERT INTO xtbooks VALUES ( XMLTYPE ( ' <cover> <title>Java Programming with Oracle JDBC</title> <author>Donald Bales</author> <publisher>OReilly and Associates</publisher> <pubdate>December 2001</pubdate> <isbn>0-596-00088-x</isbn> <pages>496</pages> </cover> ' ) );
COMMIT;
Упражнение. Проверьте реакцию СУБД на попытку вставить в таблицу XTBOOKS правильно оформленный документ XML, не соответствующий описанию схемы.
Аналогично накладываются дополнительные ограничения на данные столбца XMLTYPE в обычной таблице:
CREATE TABLE tbooks ( id NUMBER ( 9 ) , description XMLTYPE ) XMLTYPE description STORE AS OBJECT RELATIONAL XMLSCHEMA "http://localhost:8080/public/bookCover.xsd" ELEMENT "cover" ;
В приведенных примерах данные в БД фактически будут храниться «объектно-реляционно», то есть будучи распределены по разным структурам БД, в том числе по спрятанным столбцам таблиц. Однако типизируя таблицу или столбец типа XMLTYPE схемой, можно потребовать фактического хранения документа в виде объекта CLOB, подобно тому, как это происходит при отсутствии типизации схемой.
Пример:
CREATE TABLE xtbooksclob OF XMLTYPE XMLTYPE STORE AS CLOB
XMLSCHEMA "http://localhost:8080/public/bookCover.xsd" ELEMENT "cover" ;
Упражнение. Проверить возникновение новых объектов БД и их структуры по результатам заведения таблиц XTBOOKS, TBOOKS и XTBOOKSCLOB. Воспользоваться для этого таблицами USER_OBJECTS, USER_TAB_COLS, USER_TYPES, USER_TRIGGERS, USER_LOBS.
При отсутствии XML DB не заперщено создавать производную таблицу (view), выдающую данные в виде таблицы документов XML (типа XMLTYPE) на основе данных из обычных таблиц. Рассмотрим, как при наличии XML DB можно дополнительно уточнить такую производную таблицу схемой XML.
В этом примере регистрируется схема, не взятая из ресурса репозитария, как ранее, а явно выписанная в виде текста XML:
BEGIN DBMS_XMLSCHEMA.REGISTERSCHEMA ( schemaurl => 'http://localhost:8080/public/employee.xsd'
, schemadoc => '<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:element name="employee"> <xs:complexType> <xs:sequence> <xs:element name="ename" type="xs:string"/> <xs:element name="job" type="xs:string"/> <xs:element name="sal" type="xs:integer"/> </xs:sequence> <xs:attribute name="empno" type="xs:integer"/> </xs:complexType> </xs:element> </xs:schema> ' ); END; /
Пример создания производной таблицы:
CREATE OR REPLACE VIEW empxml_schema_view OF XMLTYPE XMLSCHEMA "http://localhost:8080/public/employee.xsd" ELEMENT "employee" WITH OBJECT ID ( EXTRACT ( SYS_NC_ROWINFO$, '/employee/@empno' ).GETNUMBERVAL ( ) ) AS SELECT XMLELEMENT ( "employee" , XMLATTRIBUTES ( e.empno AS "empno" ) , XMLFOREST ( e.ename AS "ename", e.job AS "job", e.sal AS "sal" ) ) FROM emp e ;
Наличие данных, противоречащих схеме, не препятствует извлечению данных результата при обращении к созданой производной таблице. Однако ж имеется метод, способный выполнить проверку соответствия схеме:
SELECT VALUE ( v ).ISSCHEMAVALID ( ) FROM empxml_schema_view v;
Упражнение. Создать производную таблицу EMLXML_VIEW по аналогии с EMLXML_SCHEMA_VIEW, не уточненной схемой (для этого потребуется удалить из определения выше две строки, выделенные жирным шрифтом). Выполнить следующие проверки:
Рассмотрим несложную схему XML, определение которой создадим в файле bookCover.xsd:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <xsd:element name="cover" type="coverType"/> <xsd:complexType name="coverType"> <xsd:sequence> <xsd:element name="title" type="xsd:string"/> <xsd:element name="author" type="xsd:string" maxOccurs="unbounded"/> <xsd:element name="publisher" type="xsd:string"/> <xsd:element name="pubdate" type="xsd:string"/> <xsd:element name="isbn" type="xsd:string"/> <xsd:element name="pages" type="xsd:string"/> </xsd:sequence> </xsd:complexType> </xsd:schema>
Поместим файл bookCover.xsd в репозитарий XML DB в папку /public (любым методом: командной строкой, программно, графическим способом, по WebDAV или же по FTP). Получим ресурс /public/bookCover.xsd репозитария. Зарегистрируем схему, являющуюся содержанием этого ресурса, с помощью пользователя SCOTT.
Для возможности регистрации схемы пользователь БД должен обладать привилегиями
ALTER SESSION CREATE TYPE CREATE TABLE CREATE PROCEDURE CREATE TRIGGER
В версии 10 содержание роли CONNECT было сведено только к привилегии CREATE SESSION, поэтому после версии 9 пользователю SCOTT потребуется так или иначе выдать привилегию ALTER SESSION, например:
CONNECT / AS SYSDBA
GRANT ALTER SESSION TO scott;
CONNECT scott/tiger
Следующая далее команда не является технологической необходимостью и выдается для возможности дальнейшего анализа произошедшего:
ALTER SESSION SET EVENTS='31098 trace name context forever';
Регистрация:
BEGIN DBMS_XMLSCHEMA.REGISTERSCHEMA ( schemaurl => 'http://localhost:8080/public/bookCover.xsd' , schemadoc => XDBURITYPE ( '/public/bookCover.xsd' )
); END; /
Описание схемы не обязательно заводить в репозитарии в качестве ресурса. Для регистрации можно воспользоваться и внешним файлом, явно указанным документом XML или же документом, указанным через внешний URL (подтипы URITYPE).
,
Преподаватель технологий Oracle
Чиновник по особым порученьям, Который их до места проводил, С заботливым Попова попеченьем Сдал на руки дежурному. А. К. Толстой. Сон Попова |
Метод CREATESCHEMABASEDXML типа XMLTYPE позволяет устроить проверку соответствия документа XML схеме.
Ради краткости записи следующих примеров имя зарегистрированной схемы занесем в переменную SQL*Plus:
VARIABLE bookschema VARCHAR2 ( 100 ) EXECUTE :bookschema := 'http://localhost:8080/public/bookCover.xsd'
Следующие запросы проработают без ошибок:
SELECT XMLTYPE ( '<cover></cover>' ).CREATESCHEMABASEDXML ( :bookschema )
FROM dual ;
SELECT XMLTYPE ( '<cover><author>Einstein</author></cover>' ) .CREATESCHEMABASEDXML ( :bookschema ) FROM dual ;
SELECT XMLTYPE ( ' <cover> <title>Java Programming with Oracle JDBC</title> <author>Donald Bales</author> <publisher>OReilly and Associates</publisher> <pubdate>December 2001</pubdate> <isbn>0-596-00088-x</isbn> <pages>496</pages> </cover> ' ).CREATESCHEMABASEDXML ( :bookschema ) FROM dual ;
Следующие запросы проработают с ошибками ввиду противоречий документа схеме:
SELECT XMLTYPE ( '<c/>' ).CREATESCHEMABASEDXML ( :bookschema ) FROM dual ;
SELECT XMLTYPE ( '<cover><a>Einstein</a></cover>' ) .CREATESCHEMABASEDXML ( :bookschema ) FROM dual ;
SELECT XMLTYPE ( '<cover><title>A</title><title>B</title></cover>' ) .CREATESCHEMABASEDXML ( :bookschema ) FROM dual ;
Для обратного преобразования удобно воспользоваться функциями, объединенными в стандарте SQL:2003 названием SQL/XML (другое название – SQLX). В версии Oracle 9.2 реализованы следующие (не все) функции из этого стандартного набора:
- XMLElement
- XMLAttributes
- XMLAgg
- XMLConcat
- XMLForest
Вот некоторые примеры использования в схеме SCOTT:
SELECT XMLELEMENT("Employee", ename) FROM emp;
SELECT XMLELEMENT("Employee",
XMLATTRIBUTES(ename AS "Name", empno AS "Number"))
FROM emp;
Обратите внимание, что в результатах выдаются поля типа XMLTYPE:
CREATE TABLE xtable (n) AS SELECT XMLELEMENT("Name", ename) FROM emp;
DESCRIBE xtable
Следующий пример – агрегирующей функции XMLAGG, допускающей использование в запросах с группировкой GROUP BY, подобно тому, как агрегирующие функции MIN, AVG и другие применяются для обычных данных, а не XMLTYPE:
SET LONG 2000
SELECT XMLELEMENT("department", XMLATTRIBUTES(deptno AS "no")),
XMLAGG(XMLELEMENT("employee", ename))
FROM emp
GROUP BY deptno;
Интересно, что последний запрос допускает создания на своей основе выводимой таблицы, но не базовой:
CREATE VIEW xview (a, b) AS
SELECT XMLELEMENT("department", XMLATTRIBUTES(deptno AS "no")),
XMLAGG(XMLELEMENT("employee", ename))
FROM emp
GROUP BY deptno;
(срабатывает)
CREATE TABLE xtable (a, b) AS
SELECT XMLELEMENT("department", XMLATTRIBUTES(deptno AS "no")),
XMLAGG(XMLELEMENT("employee", ename))
FROM emp
GROUP BY deptno;
(ошибка !)
Это объясняется тем, что столбцы A и B в обоих случаях Oracle пытается создавать как XMLTYPE, а наши данные таковы, что в столбце B содержатся строго говоря некорректные строки XML, например
<employee>CLARK</employee><employee>KING</employee> ....
Однако в случае выводимой таблицы Oracle смотрит на это сквозь пальцы, а в случае базовой – нет. Возможно это есть следствие определенной недоработанности некоторых областей технологий XML в Oracle, что вызвано чересчур быстрыми темпами развития этих технологий.
Для преобразования данных типа XMLTYPE в обычный табличный вид можно использовать функции SQL и методы XMLTYPE, в первую очередь упоминавшуюся метод-функцию EXTRACT:
COLUMN xdoc FORMAT A80
SELECT ROWNUM, id, b.description.EXTRACT('/cover/author') xdoc
FROM books b;
Обратите внимание на возможность и способ обработки нескольких авторов в XML элементах <author>.
Использование функции SQL EXTRACTVALUE, в свою очередь, оставляет возможность отбора не более одного элемента XML для формирования каждой строки результата SELECT, но зато безболезнено убирает обрамляющие значение элемента XML метки:
SELECT id, EXTRACTVALUE(b.description.EXTRACT('/cover/title'), '/title') xdoc
FROM books b;
То же самое можно записать проще, что уже демонстрировалось в начале статьи.
CREATE TABLE books
(id NUMBER PRIMARY KEY
, description XMLTYPE);
INSERT INTO books VALUES
(100
, XMLTYPE('<cover>
<title>Oracle SQL*Loader</title>
<author>Jonathan Gennick</author>
<author>Sanjay Mishra</author>
<pages>269</pages>
</cover>'));
SET long 1000
SELECT id, description FROM books;
SELECT id, b.description.XMLDATA FROM books b;
XMLDATA – специально созданный для XMLTYPE «псевдостолбец».
Связь двух форм описания данных – табличной и XML – достигается не одною только возможностью создавать в таблицах столбец типа XMLTYPE. Возможно преобразование данных из одного вида в другой, благодаря чему исходный формат хранения данных может оказаться не столь существенен.
Доказательством утверждения в заголовке служит создание следующей таблицы объектов типа XMLTYPE, «таблицы документов XML»:
CREATE TABLE xbooks OF XMLTYPE;
Работать с ними можно, как и с XML-атрибутом в обычной таблице:
INSERT INTO xbooks VALUES
(XMLTYPE('<cover>
<title>Oracle SQL*Loader</title>
<author>Jonathan Gennick</author>
<author>Sanjay Mishra</author>
<pages>269</pages>
</cover>'));
INSERT INTO xbooks VALUES
(NEW XMLTYPE('<?xml version="1.0"?>
<cover>
<title>SQL*Plus Pocket Reference</title>
<author>Jonathan Gennick</author>
<pages>94</pages>
</cover>'));
В первом случае объект XML создается с помощью конструктора, а во втором, к тому же, используется оператор NEW. Последний применяется в Oracle для работы с объектами, однако его использование носит лишь рекомендательный характер, так как в SQL он ничего содержательного не дает.
Далее:
SELECT * FROM xbooks;
SELECT VALUE(x) FROM xbooks x;
SELECT XMLDATA FROM xbooks;
XMLTYPE дает возможность сообщить БД, что заносимый текст – это не просто строка, а строка документа XML. Следующая попытка приведет к ошибке:
INSERT INTO books VALUES (101, XMLTYPE('<cover><title></title>'));
С дугой стороны, Oracle поймет правильно составленные директивы XML и встроенное в текст описание DTD:
INSERT INTO books VALUES
(101
, XMLTYPE('<?xml version="1.0"?>
<!DOCTYPE cover [
<!ELEMENT cover (title, author*, pages)>
<!ELEMENT title (#PCDATA)>
<!ELEMENT author (#PCDATA)>
<!ELEMENT pages (#PCDATA)>
]>
<cover>
<title>SQL*Plus Pocket Reference</title>
<author>Jonathan Gennick</author>
<pages>94</pages>
</cover>'));
Убедитесь в этом сами, что Oracle действительно соотносит описание DTD самому тексту документа !
Для выборки можно использовать специально придуманные для XMLTYPE функции. Так, функция EXTRACTVALUE извлекает значения элемента из документа XML:
SELECT id, EXTRACTVALUE(description, '/cover/title')
FROM books;
Функция EXISTSNODE дает возможность использовать в SQL условие отбора XPath (язык отбора, принятый в технологиях XML):
SELECT id, b.description.XMLDATA
FROM books b
WHERE b.description.EXISTSNODE('/cover[author="Sanjay Mishra"]')=1;