Как я могу интегрировать безопасность на уровне строк Oracle с MyBatis? - PullRequest
2 голосов
/ 28 июля 2011

Проект, над которым я работаю, использует базу данных Oracle с безопасностью на уровне строк.Мне нужно иметь возможность вызывать call DBMS_APPLICATION_INFO.SET_CLIENT_INFO('userId');, прежде чем я смогу выполнить любые другие операторы SQL.Я пытаюсь найти способ реализовать это в MyBatis.Несколько идей, которые у меня были, но я не смог заставить их работать, включают следующее:

Попытка 1

<select id="selectIds" parameterType="string" resultType="Integer">
      call DBMS_APPLICATION_INFO.SET_CLIENT_INFO(#{userId});
    select id from FOO
</select>

Однако вы не можете сделать два оператора в одном вызове JDBC, а MyBatis неУ меня нет поддержки для пакетных операторов JDBC, или, по крайней мере, я не смог их найти.

Попытка 2

<select id="selectMessageIds" parameterType="string" resultType="Integer">
    <![CDATA[
        declare
           type ID_TYP is table of AGL_ID.ID_ID%type;
           ALL_IDS ID_TYP;
        begin
           DBMS_APPLICATION_INFO.SET_CLIENT_INFO(#{userId});
           select ID bulk collect
             into ALL_IDS
             from FOO
        end;
    ]]>
</select>

Однако, насколько я понял, я понял, что вы можете 't вернуть данные в процедуре, только в функции, поэтому не было никакого способа вернуть данные.

Попытка 3

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

Информация о версии программного обеспечения / платформы

Oracle 10g
MyBatis 3.0.5
Spring 3.0.5

Обновление
Забыл упомянуть, что я также использую MyBatis Spring 1.0.1

Ответы [ 2 ]

2 голосов
/ 01 августа 2011

Звучит как идеальный кандидат для транзакций. Вы можете создать базовый класс @Transactional службы (или DAO), который выполняет вызов функции DBMS_APPLICATION. Все остальные ваши классы обслуживания могут расширять базу и вызывать необходимый SQL.

В базовом классе вы хотите убедиться, что вызываете функцию DBMS_APPLICATION только один раз. Для этого используйте методы TransactionSynchronizationManager.hasResource() и bindResource(), чтобы привязать логическое или подобное значение маркера к текущему TX. Проверьте это значение, чтобы определить, нужно ли вам вызвать функцию или нет.

Если вызов функции существует только для «единицы работы» в БД, это должно быть все, что вам нужно. Если вызов существует на время соединения, базовый класс должен будет как-то слишком тщательно очищаться в блоке finally.

Вместо базового класса другой возможностью было бы использование AOP и выполнение вызова функции перед вызовом метода и очисткой в ​​качестве окончательного совета. Ключевым моментом здесь было бы убедиться, что ваш перехватчик вызывается после Spring TransactionInterceptor (т.е. после запуска tx).

0 голосов
/ 29 июля 2011

Одним из самых безопасных решений было бы иметь конкретизированные DatSourceUtils

1 : http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/jdbc/datasource/DataSourceUtils.html и переопределить doGetConnection (DataSource dataSource) и setClientInfoпри подключении

Для передачи информации о клиенте напишите собственную абстракцию через SqlMapClientDaoSupport .

...