我正在使用一个具有大约 150 个服务的 spring 应用程序,因此我需要审核每个服务的每个 http 事件请求(发布、放置和删除),其中的审核数据应该是发出 http 请求的用户它必须存储在数据库中。
为了实现这一点,在 Spring 方面,我创建了一个 http 拦截器来获取用户并将其存储在使用 java 创建的 Postgres Temp 表中。
// The Interceptor
@Component
public class AuditHttpRequestHandlerInterceptor implements HandlerInterceptor {
@Inject private AuditBasicAuthExtractor auditBasicAuthExtractor;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
try {
String user = auditBasicAuthExtractor.getUser();
auditBasicAuthExtractor.addTempTable(user);
} catch (Exception ex) {
LOGGER.error("", ex);
}
return true;
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
}
}
// Temp Table Creation
private void createNewTempTable(DataSource dataSource, String tempTableName, List<String> columns) {
Connection connection = null;
PreparedStatement preparedStatement = null;
try {
connection = dataSource.getConnection();
String sqlStatement = "CREATE TEMP TABLE IF NOT EXISTS ".concat(tempTableName).concat(" ( ");//here I create the temp table
for (String column:
columns) {
sqlStatement = sqlStatement.concat(column);// one of the columns is the user
}
sqlStatement = sqlStatement.concat(")");
preparedStatement = connection.prepareStatement(sqlStatement);
preparedStatement.executeUpdate();
} catch (SQLException throwables) {
LOGGER.error("SQLException ", throwables);
} finally {
try {
if (preparedStatement != null) {
preparedStatement.close();
}
if (connection != null) {
connection.close();
}
} catch (SQLException throwables) {
LOGGER.error("SQLException", throwables);
}
}
}
在 Postgres 上,我创建了一个插入、更新和删除后触发器,该触发器参考临时表以获取相应的用户,之后触发器将此用户存储在审计表中(在父审计表中,我存储用户和子审计表我存储修改后的列名和旧值和新值)。
// Piece of code of the trigger
CREATE OR REPLACE FUNCTION audit_changes() RETURNS TRIGGER AS $$
DECLARE
BEGIN
IF EXISTS(SELECT 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'temp_user_table') THEN
SELECT user_id INTO user_name FROM cloud_context; --here fetches the user
END IF;
END;
$$ LANGUAGE plpgsql;
这适用于 2 或 3 个并发的不同用户(触发器正确获取每个用户)。
但是假设我们有 50 个不同的并发用户同时发出请求。在这种情况下,临时表存储 50 个不同的行(每个用户一个),因此在这种情况下,触发器无法识别哪个用户发出了相应的请求。
我想在拦截器中包含一个唯一标识符,目的是触发器可以通过该标识符选择用户,但我不知道如何在拦截器和触发器之间共享该 ID。
我将不胜感激任何帮助或指导来解决这个问题,任何替代解决方案也会很好。