Пользователи приложений в политиках на уровне строк: как установить переменные сеанса
Я пытаюсь написать политики на уровне строк, которые проверяют права пользователя перед выполнением запросов. В этом контексте мне нужно иметь возможность устанавливать переменную сеанса, содержащую идентификатор пользователя, когда соединение выбирается из пула соединений, и отменять / освобождать эту же переменную сеанса, когда соединение возвращается обратно в пул. Следующий блог может дать хороший фон, чтобы объяснить, что я пытаюсь сделать: https://blog.2ndquadrant.com/application-users-vs-row-level-security/
В моей настройке у меня есть следующие слои:
- Хикари:
HikariDataSource
- Весна:
TransactionAwareDataSourceProxy
(используя источник данных Hikari),DataSourceTransactionManager
(используя источник данных Hikary) - jOOQ:
DataSourceConnectionProvider
(используя источник данных Spring),DefaultDSLContext
Первые два слоя только внутренние. То есть все запросы в приложении выполняются через последний уровень jOOQ.
Итак, мне нужно иметь возможность реализовать обратный вызов при подключении take from pool
а также give back to pool
,
Я просматривал документацию по Hikari и Spring, но не смог найти ничего полезного. Вероятно, это мой первый вопрос: предоставляют ли Hikari и / или Spring такие обратные вызовы?
Следующим шагом в моем расследовании был JOOQ. Я наткнулся на ExecuteListener
, Это мой дополнительный вопрос: будет ExecuteListener
быть хорошим приложением для этого? Это не реализует фактическую точку, когда соединение взято и возвращено, но execution context
вероятно, достаточно хорош в моем случае (так как все мои запросы выполняются в jOOQ)? Если это так, я должен реализовать start
а также end
функции?
1 ответ
Это можно решить на разных уровнях вашего текущего стека. Вот два предложения:
Решая это в DataSource
/ Connection
полномочие
Большинство пулов соединений реализуют следующую семантику:
DataSource.getConnection()
: "Возьми из пула"Connection.close()
: "Отдай обратно в бассейн"
Таким образом, вы можете проксировать эти два API и реализовать желаемую семантику внутри этих соответствующих методов. Это немного больше работы, но она будет работать с любым клиентом JDBC, включая jOOQ (т.е. он также будет работать, когда вы не используете jOOQ)
Решая это в JOOQ
Если все ваши взаимодействия с базой данных проходят через jOOQ, вы можете решить эту проблему проще с помощью jOOQ напрямую, используя ConnectionProvider
SPI, который содержит два метода, которые имеют именно ту семантику, которая вам требуется:
ConnectionProvider.acquire()
ConnectionProvider.release(Connection)
Таким образом, вместо использования JOOQ "из коробки" DataSourceConnectionProvider
Вы могли бы сделать это:
public class MyConnectionProvider implements ConnectionProvider {
// Configure spring to inject your data source here
@Autowire
DataSource ds;
@Override
public Connection acquire() {
try {
Connection c = ds.getConnection();
// Do your stuff here
return c;
}
catch (SQLException e) {
throw new DataAccessException("Something failed", e);
}
}
@Override
public void release(Connection c) {
try {
// Do your stuff here
c.close();
}
catch (SQLException e) {
throw new DataAccessException("Something failed", e);
}
}
}
Вы могли бы сделать это с ExecuteListener
тоже, но вышеуказанный подход, конечно, проще.