This is an automated email from the ASF dual-hosted git repository.

yongzao pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/iotdb.git


The following commit(s) were added to refs/heads/master by this push:
     new c2696b33ae4 Add audit logic for login and logout event (#16520)
c2696b33ae4 is described below

commit c2696b33ae49a070e27a701988091d5cca4b9ff3
Author: wenyanshi-123 <[email protected]>
AuthorDate: Wed Oct 1 11:01:00 2025 +0800

    Add audit logic for login and logout event (#16520)
---
 .../iotdb/it/env/cluster/env/AbstractEnv.java      |   2 +-
 .../itbase/runtime/ClusterTestConnection.java      |  10 +-
 .../iotdb/itbase/runtime/ClusterTestStatement.java |   4 +-
 .../iotdb/itbase/runtime/NodeConnection.java       |  12 +-
 .../iotdb/db/it/audit/IoTDBAuditLogBasicIT.java    | 361 +++++++++++++++++++--
 .../persistence/auth/AuthorPlanExecutor.java       |   5 +-
 .../org/apache/iotdb/db/audit/DNAuditLogger.java   |   2 +
 .../iotdb/db/protocol/session/SessionManager.java  |  66 ++--
 .../protocol/thrift/impl/ClientRPCServiceImpl.java |  17 +
 .../auth/authorizer/LocalFileAuthorizerTest.java   |   2 +-
 .../apache/iotdb/commons/audit/AuditEventType.java |   1 +
 .../apache/iotdb/commons/audit/AuditLogFields.java |  19 ++
 .../commons/auth/authorizer/BasicAuthorizer.java   |   5 +-
 13 files changed, 444 insertions(+), 62 deletions(-)

diff --git 
a/integration-test/src/main/java/org/apache/iotdb/it/env/cluster/env/AbstractEnv.java
 
b/integration-test/src/main/java/org/apache/iotdb/it/env/cluster/env/AbstractEnv.java
index c207ca8ac4c..8308225a9af 100644
--- 
a/integration-test/src/main/java/org/apache/iotdb/it/env/cluster/env/AbstractEnv.java
+++ 
b/integration-test/src/main/java/org/apache/iotdb/it/env/cluster/env/AbstractEnv.java
@@ -679,7 +679,7 @@ public abstract class AbstractEnv implements BaseEnv {
         ? new ClusterTestConnection(
             getWriteConnection(version, username, password, sqlDialect),
             getReadConnections(version, username, password, sqlDialect))
-        : getWriteConnection(version, username, password, 
sqlDialect).getUnderlyingConnecton();
+        : getWriteConnection(version, username, password, 
sqlDialect).getUnderlyingConnection();
   }
 
   @Override
diff --git 
a/integration-test/src/main/java/org/apache/iotdb/itbase/runtime/ClusterTestConnection.java
 
b/integration-test/src/main/java/org/apache/iotdb/itbase/runtime/ClusterTestConnection.java
index 77a5136e696..e272583b08a 100644
--- 
a/integration-test/src/main/java/org/apache/iotdb/itbase/runtime/ClusterTestConnection.java
+++ 
b/integration-test/src/main/java/org/apache/iotdb/itbase/runtime/ClusterTestConnection.java
@@ -43,8 +43,8 @@ import java.util.concurrent.Executor;
 /** The implementation of {@link Connection} in cluster test. */
 public class ClusterTestConnection implements Connection {
 
-  private final NodeConnection writeConnection;
-  private final List<NodeConnection> readConnections;
+  public final NodeConnection writeConnection;
+  public final List<NodeConnection> readConnections;
   private boolean isClosed;
 
   public ClusterTestConnection(
@@ -110,7 +110,7 @@ public class ClusterTestConnection implements Connection {
 
   @Override
   public DatabaseMetaData getMetaData() throws SQLException {
-    return writeConnection.getUnderlyingConnecton().getMetaData();
+    return writeConnection.getUnderlyingConnection().getMetaData();
   }
 
   @Override
@@ -269,9 +269,9 @@ public class ClusterTestConnection implements Connection {
 
   @Override
   public void setClientInfo(String name, String value) throws 
SQLClientInfoException {
-    writeConnection.getUnderlyingConnecton().setClientInfo(name, value);
+    writeConnection.getUnderlyingConnection().setClientInfo(name, value);
     for (NodeConnection conn : readConnections) {
-      conn.getUnderlyingConnecton().setClientInfo(name, value);
+      conn.getUnderlyingConnection().setClientInfo(name, value);
     }
   }
 
diff --git 
a/integration-test/src/main/java/org/apache/iotdb/itbase/runtime/ClusterTestStatement.java
 
b/integration-test/src/main/java/org/apache/iotdb/itbase/runtime/ClusterTestStatement.java
index f5dc5289d12..3f96fdf1372 100644
--- 
a/integration-test/src/main/java/org/apache/iotdb/itbase/runtime/ClusterTestStatement.java
+++ 
b/integration-test/src/main/java/org/apache/iotdb/itbase/runtime/ClusterTestStatement.java
@@ -51,7 +51,7 @@ public class ClusterTestStatement implements Statement {
   public ClusterTestStatement(
       NodeConnection writeConnection, List<NodeConnection> readConnections) {
     try {
-      this.writeStatement = 
writeConnection.getUnderlyingConnecton().createStatement();
+      this.writeStatement = 
writeConnection.getUnderlyingConnection().createStatement();
       updateConfig(writeStatement, 0);
       writEndpoint = writeConnection.toString();
     } catch (SQLException e) {
@@ -60,7 +60,7 @@ public class ClusterTestStatement implements Statement {
 
     for (NodeConnection readConnection : readConnections) {
       try {
-        Statement readStatement = 
readConnection.getUnderlyingConnecton().createStatement();
+        Statement readStatement = 
readConnection.getUnderlyingConnection().createStatement();
         this.readStatements.add(readStatement);
         this.readEndpoints.add(readConnection.toString());
         updateConfig(readStatement, queryTimeout);
diff --git 
a/integration-test/src/main/java/org/apache/iotdb/itbase/runtime/NodeConnection.java
 
b/integration-test/src/main/java/org/apache/iotdb/itbase/runtime/NodeConnection.java
index e3508422aa8..8f9eddcf3f4 100644
--- 
a/integration-test/src/main/java/org/apache/iotdb/itbase/runtime/NodeConnection.java
+++ 
b/integration-test/src/main/java/org/apache/iotdb/itbase/runtime/NodeConnection.java
@@ -33,17 +33,17 @@ public class NodeConnection {
   private final String endpoint;
   private final NodeRole nodeRole;
   private final ConnectionRole connectionRole;
-  private final Connection underlyingConnecton;
+  private final Connection underlyingConnection;
 
   public NodeConnection(
       String endpoint,
       NodeRole nodeRole,
       ConnectionRole connectionRole,
-      Connection underlyingConnecton) {
+      Connection underlyingConnection) {
     this.endpoint = endpoint;
     this.nodeRole = nodeRole;
     this.connectionRole = connectionRole;
-    this.underlyingConnecton = underlyingConnecton;
+    this.underlyingConnection = underlyingConnection;
   }
 
   public String getEndpoint() {
@@ -58,13 +58,13 @@ public class NodeConnection {
     return connectionRole;
   }
 
-  public Connection getUnderlyingConnecton() {
-    return underlyingConnecton;
+  public Connection getUnderlyingConnection() {
+    return underlyingConnection;
   }
 
   public void close() {
     try {
-      underlyingConnecton.close();
+      underlyingConnection.close();
     } catch (SQLException e) {
       logger.error("Close connection {} error", this, e);
     }
diff --git 
a/integration-test/src/test/java/org/apache/iotdb/db/it/audit/IoTDBAuditLogBasicIT.java
 
b/integration-test/src/test/java/org/apache/iotdb/db/it/audit/IoTDBAuditLogBasicIT.java
index 4d96a41406c..39a51468082 100644
--- 
a/integration-test/src/test/java/org/apache/iotdb/db/it/audit/IoTDBAuditLogBasicIT.java
+++ 
b/integration-test/src/test/java/org/apache/iotdb/db/it/audit/IoTDBAuditLogBasicIT.java
@@ -26,6 +26,8 @@ import org.apache.iotdb.it.env.EnvFactory;
 import org.apache.iotdb.it.framework.IoTDBTestRunner;
 import org.apache.iotdb.itbase.category.LocalStandaloneIT;
 import org.apache.iotdb.itbase.env.BaseEnv;
+import org.apache.iotdb.itbase.runtime.ClusterTestConnection;
+import org.apache.iotdb.itbase.runtime.NodeConnection;
 
 import org.junit.After;
 import org.junit.Assert;
@@ -96,7 +98,7 @@ public class IoTDBAuditLogBasicIT {
   private static final String AUDITABLE_OPERATION_RESULT = "SUCCESS,FAIL";
 
   @Before
-  public void setUp() throws SQLException {
+  public void setUp() throws SQLException, InterruptedException {
     EnvFactory.getEnv()
         .getConfig()
         .getCommonConfig()
@@ -108,27 +110,38 @@ public class IoTDBAuditLogBasicIT {
     // Init 1C1D cluster environment
     EnvFactory.getEnv().initClusterEnvironment(1, 1);
 
-    try (Connection connection = 
EnvFactory.getEnv().getConnection(BaseEnv.TREE_SQL_DIALECT);
-        Statement statement = connection.createStatement()) {
-      // Ensure there exists audit database in tree model
-      ResultSet resultSet = statement.executeQuery("SHOW DATABASES 
root.__audit");
-      Assert.assertTrue(resultSet.next());
-      Assert.assertEquals("root.__audit", resultSet.getString(1));
+    Connection connection = 
EnvFactory.getEnv().getConnection(BaseEnv.TREE_SQL_DIALECT);
+    Statement statement = connection.createStatement();
+    ResultSet resultSet = statement.executeQuery("SHOW DATABASES 
root.__audit");
+    Assert.assertTrue(resultSet.next());
+    Assert.assertEquals("root.__audit", resultSet.getString(1));
+    Thread.sleep(1000);
+    ((ClusterTestConnection) connection).writeConnection.close();
+    Thread.sleep(1000);
+    for (NodeConnection conn : ((ClusterTestConnection) 
connection).readConnections) {
+      Thread.sleep(1000);
+      conn.close();
+      Thread.sleep(1000);
     }
-
-    try (Connection connection = 
EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
-        Statement statement = connection.createStatement()) {
-      // Ensure there exists audit table
-      ResultSet resultSet = statement.executeQuery("DESC __audit.audit_log");
-      resultSet.next(); // Skip time column
-      int cnt = 0;
-      while (resultSet.next()) {
-        Assert.assertEquals(AUDIT_TABLE_COLUMNS.get(cnt), 
resultSet.getString(1));
-        Assert.assertEquals(AUDIT_TABLE_DATA_TYPES.get(cnt), 
resultSet.getString(2));
-        Assert.assertEquals(AUDIT_TABLE_CATEGORIES.get(cnt), 
resultSet.getString(3));
-        cnt++;
-      }
-      Assert.assertEquals(AUDIT_TABLE_COLUMNS.size(), cnt);
+    connection = EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
+    statement = connection.createStatement();
+    resultSet = statement.executeQuery("DESC __audit.audit_log");
+    resultSet.next(); // Skip time column
+    int cnt = 0;
+    while (resultSet.next()) {
+      Assert.assertEquals(AUDIT_TABLE_COLUMNS.get(cnt), 
resultSet.getString(1));
+      Assert.assertEquals(AUDIT_TABLE_DATA_TYPES.get(cnt), 
resultSet.getString(2));
+      Assert.assertEquals(AUDIT_TABLE_CATEGORIES.get(cnt), 
resultSet.getString(3));
+      cnt++;
+    }
+    Assert.assertEquals(AUDIT_TABLE_COLUMNS.size(), cnt);
+    Thread.sleep(1000);
+    ((ClusterTestConnection) connection).writeConnection.close();
+    Thread.sleep(1000);
+    for (NodeConnection conn : ((ClusterTestConnection) 
connection).readConnections) {
+      Thread.sleep(1000);
+      conn.close();
+      Thread.sleep(1000);
     }
   }
 
@@ -176,7 +189,60 @@ public class IoTDBAuditLogBasicIT {
               "null",
               "null",
               "Successfully start the Audit service with configurations 
(auditableOperationType [DDL, DML, QUERY, CONTROL], auditableOperationLevel 
GLOBAL, auditableOperationResult SUCCESS,FAIL)"),
-          // Show audit database
+
+          // Environment init login/logout
+          Arrays.asList(
+              "node_1",
+              "u_0",
+              "root",
+              "127.0.0.1",
+              "LOGIN",
+              "CONTROL",
+              "null",
+              "GLOBAL",
+              "true",
+              "",
+              "",
+              "IoTDB: Login status: Login successfully. User root (ID=0), 
opens Session"),
+          Arrays.asList(
+              "node_1",
+              "u_0",
+              "root",
+              "127.0.0.1",
+              "LOGOUT",
+              "CONTROL",
+              "null",
+              "GLOBAL",
+              "true",
+              "",
+              "",
+              "is closing"),
+          Arrays.asList(
+              "node_1",
+              "u_0",
+              "root",
+              "127.0.0.1",
+              "LOGIN",
+              "CONTROL",
+              "null",
+              "GLOBAL",
+              "true",
+              "",
+              "",
+              "IoTDB: Login status: Login successfully. User root (ID=0), 
opens Session"),
+          Arrays.asList(
+              "node_1",
+              "u_0",
+              "root",
+              "127.0.0.1",
+              "LOGIN",
+              "CONTROL",
+              "null",
+              "GLOBAL",
+              "true",
+              "",
+              "",
+              "IoTDB: Login status: Login successfully. User root (ID=0), 
opens Session"),
           Arrays.asList(
               "node_1",
               "u_0",
@@ -190,6 +256,60 @@ public class IoTDBAuditLogBasicIT {
               "[root.__audit]",
               "SHOW DATABASES root.__audit",
               "User root (ID=0) requests authority on object root.__audit with 
result true"),
+          // Setup logout through tree model dialect, twice for both read and 
write connections
+          Arrays.asList(
+              "node_1",
+              "u_0",
+              "root",
+              "127.0.0.1",
+              "LOGOUT",
+              "CONTROL",
+              "null",
+              "GLOBAL",
+              "true",
+              "",
+              "",
+              "is closing"),
+          Arrays.asList(
+              "node_1",
+              "u_0",
+              "root",
+              "127.0.0.1",
+              "LOGOUT",
+              "CONTROL",
+              "null",
+              "GLOBAL",
+              "true",
+              "",
+              "",
+              "is closing"),
+          // Setup login through table model dialect, twice for both read and 
write connections
+          Arrays.asList(
+              "node_1",
+              "u_0",
+              "root",
+              "127.0.0.1",
+              "LOGIN",
+              "CONTROL",
+              "null",
+              "GLOBAL",
+              "true",
+              "",
+              "",
+              "IoTDB: Login status: Login successfully. User root (ID=0), 
opens Session"),
+          Arrays.asList(
+              "node_1",
+              "u_0",
+              "root",
+              "127.0.0.1",
+              "LOGIN",
+              "CONTROL",
+              "null",
+              "GLOBAL",
+              "true",
+              "",
+              "",
+              "IoTDB: Login status: Login successfully. User root (ID=0), 
opens Session"),
           // Desc audit table
           Arrays.asList(
               "node_1",
@@ -204,6 +324,58 @@ public class IoTDBAuditLogBasicIT {
               "__audit",
               "DESC __audit.audit_log",
               "User root (ID=0) requests authority on object audit_log with 
result true"),
+          Arrays.asList(
+              "node_1",
+              "u_0",
+              "root",
+              "127.0.0.1",
+              "LOGOUT",
+              "CONTROL",
+              "null",
+              "GLOBAL",
+              "true",
+              "",
+              "",
+              "is closing"),
+          Arrays.asList(
+              "node_1",
+              "u_0",
+              "root",
+              "127.0.0.1",
+              "LOGOUT",
+              "CONTROL",
+              "null",
+              "GLOBAL",
+              "true",
+              "",
+              "",
+              "is closing"),
+          Arrays.asList(
+              "node_1",
+              "u_0",
+              "root",
+              "127.0.0.1",
+              "LOGIN",
+              "CONTROL",
+              "null",
+              "GLOBAL",
+              "true",
+              "",
+              "",
+              "IoTDB: Login status: Login successfully. User root (ID=0), 
opens Session"),
+          Arrays.asList(
+              "node_1",
+              "u_0",
+              "root",
+              "127.0.0.1",
+              "LOGIN",
+              "CONTROL",
+              "null",
+              "GLOBAL",
+              "true",
+              "",
+              "",
+              "IoTDB: Login status: Login successfully. User root (ID=0), 
opens Session"),
           // Create database
           Arrays.asList(
               "node_1",
@@ -634,6 +806,54 @@ public class IoTDBAuditLogBasicIT {
               "CHANGE_AUDIT_OPTION",
               "null",
               "null"),
+          Arrays.asList(
+              "root.__audit.log.node_1.u_0",
+              "true",
+              "GLOBAL",
+              "null",
+              "",
+              "CONTROL",
+              "IoTDB: Login status: Login successfully. User root (ID=0), 
opens Session",
+              "",
+              "LOGIN",
+              "127.0.0.1",
+              "root"),
+          Arrays.asList(
+              "root.__audit.log.node_1.u_0",
+              "true",
+              "GLOBAL",
+              "null",
+              "",
+              "CONTROL",
+              "is closing",
+              "",
+              "LOGOUT",
+              "127.0.0.1",
+              "root"),
+          Arrays.asList(
+              "root.__audit.log.node_1.u_0",
+              "true",
+              "GLOBAL",
+              "null",
+              "",
+              "CONTROL",
+              "IoTDB: Login status: Login successfully. User root (ID=0), 
opens Session",
+              "",
+              "LOGIN",
+              "127.0.0.1",
+              "root"),
+          Arrays.asList(
+              "root.__audit.log.node_1.u_0",
+              "true",
+              "GLOBAL",
+              "null",
+              "",
+              "CONTROL",
+              "IoTDB: Login status: Login successfully. User root (ID=0), 
opens Session",
+              "",
+              "LOGIN",
+              "127.0.0.1",
+              "root"),
           // Show audit database
           Arrays.asList(
               "root.__audit.log.node_1.u_0",
@@ -647,6 +867,55 @@ public class IoTDBAuditLogBasicIT {
               "OBJECT_AUTHENTICATION",
               "127.0.0.1",
               "root"),
+          Arrays.asList(
+              "root.__audit.log.node_1.u_0",
+              "true",
+              "GLOBAL",
+              "null",
+              "",
+              "CONTROL",
+              "is closing",
+              "",
+              "LOGOUT",
+              "127.0.0.1",
+              "root"),
+          Arrays.asList(
+              "root.__audit.log.node_1.u_0",
+              "true",
+              "GLOBAL",
+              "null",
+              "",
+              "CONTROL",
+              "is closing",
+              "",
+              "LOGOUT",
+              "127.0.0.1",
+              "root"),
+          Arrays.asList(
+              "root.__audit.log.node_1.u_0",
+              "true",
+              "GLOBAL",
+              "null",
+              "",
+              "CONTROL",
+              "IoTDB: Login status: Login successfully. User root (ID=0), 
opens Session",
+              "",
+              "LOGIN",
+              "127.0.0.1",
+              "root"),
+          Arrays.asList(
+              "root.__audit.log.node_1.u_0",
+              "true",
+              "GLOBAL",
+              "null",
+              "",
+              "CONTROL",
+              "IoTDB: Login status: Login successfully. User root (ID=0), 
opens Session",
+              "",
+              "LOGIN",
+              "127.0.0.1",
+              "root"),
+
           // Desc audit table
           Arrays.asList(
               "root.__audit.log.node_1.u_0",
@@ -660,6 +929,54 @@ public class IoTDBAuditLogBasicIT {
               "OBJECT_AUTHENTICATION",
               "127.0.0.1",
               "root"),
+          Arrays.asList(
+              "root.__audit.log.node_1.u_0",
+              "true",
+              "GLOBAL",
+              "null",
+              "",
+              "CONTROL",
+              "is closing",
+              "",
+              "LOGOUT",
+              "127.0.0.1",
+              "root"),
+          Arrays.asList(
+              "root.__audit.log.node_1.u_0",
+              "true",
+              "GLOBAL",
+              "null",
+              "",
+              "CONTROL",
+              "is closing",
+              "",
+              "LOGOUT",
+              "127.0.0.1",
+              "root"),
+          Arrays.asList(
+              "root.__audit.log.node_1.u_0",
+              "true",
+              "GLOBAL",
+              "null",
+              "",
+              "CONTROL",
+              "IoTDB: Login status: Login successfully. User root (ID=0), 
opens Session",
+              "",
+              "LOGIN",
+              "127.0.0.1",
+              "root"),
+          Arrays.asList(
+              "root.__audit.log.node_1.u_0",
+              "true",
+              "GLOBAL",
+              "null",
+              "",
+              "CONTROL",
+              "IoTDB: Login status: Login successfully. User root (ID=0), 
opens Session",
+              "",
+              "LOGIN",
+              "127.0.0.1",
+              "root"),
           // Create database
           Arrays.asList(
               "root.__audit.log.node_1.u_0",
diff --git 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/auth/AuthorPlanExecutor.java
 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/auth/AuthorPlanExecutor.java
index 694f37325c4..6eee2481d5b 100644
--- 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/auth/AuthorPlanExecutor.java
+++ 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/auth/AuthorPlanExecutor.java
@@ -97,12 +97,9 @@ public class AuthorPlanExecutor implements 
IAuthorPlanExecutor {
       }
     } catch (AuthException e) {
       LOGGER.error("meet error while logging in.", e);
-      status = false;
       loginMessage = e.getMessage();
-    }
-    if (!status) {
+      tsStatus.setCode(e.getCode().getStatusCode());
       tsStatus.setMessage(loginMessage != null ? loginMessage : 
"Authentication failed.");
-      tsStatus.setCode(TSStatusCode.WRONG_LOGIN_PASSWORD.getStatusCode());
       result.setStatus(tsStatus);
     }
     return result;
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/audit/DNAuditLogger.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/audit/DNAuditLogger.java
index 9043361fea0..a8a5280b444 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/audit/DNAuditLogger.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/audit/DNAuditLogger.java
@@ -141,6 +141,8 @@ public class DNAuditLogger extends AbstractAuditLogger {
           break;
         }
       }
+    } else {
+      privilegeLevel = PrivilegeLevel.GLOBAL;
     }
     InsertRowStatement insertStatement = new InsertRowStatement();
     insertStatement.setDevicePath(logDevice);
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/session/SessionManager.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/session/SessionManager.java
index bae81487f4f..bebc93b7e6b 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/session/SessionManager.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/session/SessionManager.java
@@ -20,8 +20,10 @@
 package org.apache.iotdb.db.protocol.session;
 
 import org.apache.iotdb.common.rpc.thrift.TSStatus;
+import org.apache.iotdb.commons.audit.AuditEventType;
+import org.apache.iotdb.commons.audit.AuditLogFields;
+import org.apache.iotdb.commons.audit.AuditLogOperation;
 import org.apache.iotdb.commons.audit.UserEntity;
-import org.apache.iotdb.commons.auth.entity.User;
 import org.apache.iotdb.commons.conf.CommonDescriptor;
 import org.apache.iotdb.commons.conf.IoTDBConstant;
 import org.apache.iotdb.commons.exception.IoTDBRuntimeException;
@@ -34,9 +36,6 @@ import org.apache.iotdb.commons.utils.AuthUtils;
 import org.apache.iotdb.commons.utils.CommonDateTimeUtils;
 import org.apache.iotdb.db.audit.DNAuditLogger;
 import org.apache.iotdb.db.auth.AuthorityChecker;
-import org.apache.iotdb.db.auth.BasicAuthorityCache;
-import org.apache.iotdb.db.auth.ClusterAuthorityFetcher;
-import org.apache.iotdb.db.auth.IAuthorityFetcher;
 import org.apache.iotdb.db.auth.LoginLockManager;
 import org.apache.iotdb.db.conf.IoTDBDescriptor;
 import org.apache.iotdb.db.protocol.basic.BasicOpenSessionResp;
@@ -61,7 +60,6 @@ import org.apache.iotdb.service.rpc.thrift.TSLastDataQueryReq;
 import org.apache.iotdb.service.rpc.thrift.TSProtocolVersion;
 
 import org.apache.commons.lang3.StringUtils;
-import org.apache.ratis.util.MemoizedSupplier;
 import org.apache.tsfile.read.common.block.TsBlock;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -85,6 +83,7 @@ import static 
org.apache.iotdb.db.utils.ErrorHandlingUtils.onNpeOrUnexpectedExce
 
 public class SessionManager implements SessionManagerMBean {
   private static final Logger LOGGER = 
LoggerFactory.getLogger(SessionManager.class);
+  private static final DNAuditLogger AUDIT_LOGGER = 
DNAuditLogger.getInstance();
 
   // When the client abnormally exits, we can still know who to disconnect
   /** currSession can be only used in client-thread model services. */
@@ -105,9 +104,6 @@ public class SessionManager implements SessionManagerMBean {
   public static final TSProtocolVersion CURRENT_RPC_VERSION =
       TSProtocolVersion.IOTDB_SERVICE_PROTOCOL_V3;
 
-  private static final MemoizedSupplier<IAuthorityFetcher> authorityFetcher =
-      MemoizedSupplier.valueOf(() -> new ClusterAuthorityFetcher(new 
BasicAuthorityCache()));
-
   protected SessionManager() {
     // singleton
     String mbeanName =
@@ -248,11 +244,10 @@ public class SessionManager implements 
SessionManagerMBean {
       return openSessionResp;
     }
 
-    User user = authorityFetcher.get().getUser(username);
-    boolean enableLoginLock = user != null;
+    long userId = AuthorityChecker.getUserId(username).orElse(-1L);
+    boolean enableLoginLock = userId != -1;
     LoginLockManager loginLockManager = LoginLockManager.getInstance();
-    if (enableLoginLock
-        && loginLockManager.checkLock(user.getUserId(), 
session.getClientAddress())) {
+    if (enableLoginLock && loginLockManager.checkLock(userId, 
session.getClientAddress())) {
       // Generic authentication error
       openSessionResp
           .sessionId(-1)
@@ -270,8 +265,6 @@ public class SessionManager implements SessionManagerMBean {
             .setCode(TSStatusCode.INCOMPATIBLE_VERSION.getStatusCode())
             .setMessage("The version is incompatible, please upgrade to " + 
IoTDBConstant.VERSION);
       } else {
-        User tmpUser = AuthorityChecker.getUser(username);
-        long userId = tmpUser == null ? -1 : tmpUser.getUserId();
         session.setSqlDialect(sqlDialect);
         supplySession(session, userId, username, ZoneId.of(zoneId), 
clientVersion);
         String logInMessage = "Login successfully";
@@ -314,7 +307,22 @@ public class SessionManager implements SessionManagerMBean 
{
             .sessionId(session.getId())
             .setCode(TSStatusCode.SUCCESS_STATUS.getStatusCode())
             .setMessage(logInMessage);
-
+        AUDIT_LOGGER.log(
+            new AuditLogFields(
+                userId,
+                username,
+                session.getClientAddress(),
+                AuditEventType.LOGIN,
+                AuditLogOperation.CONTROL,
+                true),
+            () ->
+                String.format(
+                    "%s: Login status: %s. User %s (ID=%d), opens Session-%s",
+                    IoTDBConstant.GLOBAL_DB_NAME,
+                    openSessionResp.getMessage(),
+                    username,
+                    userId,
+                    session));
         LOGGER.info(
             "{}: Login status: {}. User : {}, opens Session-{}",
             IoTDBConstant.GLOBAL_DB_NAME,
@@ -322,16 +330,27 @@ public class SessionManager implements 
SessionManagerMBean {
             username,
             session);
         if (enableLoginLock) {
-          loginLockManager.clearFailure(tmpUser.getUserId(), 
session.getClientAddress());
+          loginLockManager.clearFailure(userId, session.getClientAddress());
         }
       }
     } else {
       
openSessionResp.sessionId(-1).setMessage(loginStatus.message).setCode(loginStatus.code);
       if (enableLoginLock) {
-        loginLockManager.recordFailure(user.getUserId(), 
session.getClientAddress());
+        loginLockManager.recordFailure(userId, session.getClientAddress());
       }
+      AUDIT_LOGGER.log(
+          new AuditLogFields(
+              userId,
+              username,
+              session.getClientAddress(),
+              AuditEventType.LOGIN,
+              AuditLogOperation.CONTROL,
+              false),
+          () ->
+              String.format(
+                  "User %s (ID=%d) login failed with code: %d, %s",
+                  username, userId, loginStatus.getCode(), 
loginStatus.getMessage()));
     }
-
     return openSessionResp;
   }
 
@@ -345,7 +364,16 @@ public class SessionManager implements SessionManagerMBean 
{
             String.valueOf(session.getId()));
     // TODO we only need to do so when query is killed by time out  close the 
socket.
     IClientSession session1 = currSession.get();
-    return session1 == null || session == session1;
+    if (session1 != null && session != session1) {
+      LOGGER.info(
+          String.format(
+              "The client-%s is trying to close another session %s, pls check 
if it's a bug",
+              session, session1));
+      return false;
+    } else {
+      LOGGER.info(String.format("Session-%s is closing", session));
+      return true;
+    }
   }
 
   private void releaseSessionResource(IClientSession session, LongConsumer 
releaseQueryResource) {
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/thrift/impl/ClientRPCServiceImpl.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/thrift/impl/ClientRPCServiceImpl.java
index 74c2f6eda6b..9c514979e4b 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/thrift/impl/ClientRPCServiceImpl.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/thrift/impl/ClientRPCServiceImpl.java
@@ -26,6 +26,9 @@ import org.apache.iotdb.common.rpc.thrift.TSStatus;
 import org.apache.iotdb.common.rpc.thrift.TShowConfigurationResp;
 import org.apache.iotdb.common.rpc.thrift.TShowConfigurationTemplateResp;
 import org.apache.iotdb.common.rpc.thrift.TTimePartitionSlot;
+import org.apache.iotdb.commons.audit.AuditEventType;
+import org.apache.iotdb.commons.audit.AuditLogFields;
+import org.apache.iotdb.commons.audit.AuditLogOperation;
 import org.apache.iotdb.commons.client.exception.ClientManagerException;
 import org.apache.iotdb.commons.conf.CommonConfig;
 import org.apache.iotdb.commons.conf.CommonDescriptor;
@@ -44,6 +47,7 @@ import org.apache.iotdb.commons.path.PartialPath;
 import org.apache.iotdb.commons.schema.column.ColumnHeader;
 import org.apache.iotdb.commons.utils.PathUtils;
 import org.apache.iotdb.commons.utils.TimePartitionUtils;
+import org.apache.iotdb.db.audit.DNAuditLogger;
 import org.apache.iotdb.db.auth.AuthorityChecker;
 import org.apache.iotdb.db.conf.IoTDBConfig;
 import org.apache.iotdb.db.conf.IoTDBDescriptor;
@@ -235,6 +239,8 @@ public class ClientRPCServiceImpl implements 
IClientRPCServiceWithHandler {
 
   private static final Logger LOGGER = 
LoggerFactory.getLogger(ClientRPCServiceImpl.class);
 
+  private static final DNAuditLogger AUDIT_LOGGER = 
DNAuditLogger.getInstance();
+
   private static final IoTDBConfig config = 
IoTDBDescriptor.getInstance().getConfig();
 
   private static final CommonConfig COMMON_CONFIG = 
CommonDescriptor.getInstance().getConfig();
@@ -3240,6 +3246,17 @@ public class ClientRPCServiceImpl implements 
IClientRPCServiceWithHandler {
     IClientSession session = SESSION_MANAGER.getCurrSession();
     if (session != null) {
       TSCloseSessionReq req = new TSCloseSessionReq();
+      if (!session.getUsername().contains("null")) {
+        AUDIT_LOGGER.log(
+            new AuditLogFields(
+                session.getUserId(),
+                session.getUsername(),
+                session.getClientAddress(),
+                AuditEventType.LOGOUT,
+                AuditLogOperation.CONTROL,
+                true),
+            () -> String.format("Session-%s is closing", session));
+      }
       closeSession(req);
     }
     PipeDataNodeAgent.receiver().thrift().handleClientExit();
diff --git 
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/auth/authorizer/LocalFileAuthorizerTest.java
 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/auth/authorizer/LocalFileAuthorizerTest.java
index 300a7c0646d..96a40d0c90d 100644
--- 
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/auth/authorizer/LocalFileAuthorizerTest.java
+++ 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/auth/authorizer/LocalFileAuthorizerTest.java
@@ -65,7 +65,7 @@ public class LocalFileAuthorizerTest {
   @Test
   public void testLogin() throws AuthException {
     Assert.assertTrue(authorizer.login("root", "root"));
-    Assert.assertFalse(authorizer.login("root", "error"));
+    Assert.assertThrows(AuthException.class, () -> authorizer.login("root", 
"error"));
   }
 
   @Test
diff --git 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/audit/AuditEventType.java
 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/audit/AuditEventType.java
index 39b13835481..510912a302f 100644
--- 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/audit/AuditEventType.java
+++ 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/audit/AuditEventType.java
@@ -33,6 +33,7 @@ public enum AuditEventType {
   LOGIN_FAIL_MAX_TIMES,
   MODIFY_PASSWD,
   LOGIN,
+  LOGOUT,
   LOGIN_FINAL,
   MODIFY_SECURITY_OPTIONS,
   MODIFY_DEFAULT_SECURITY_VALUES,
diff --git 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/audit/AuditLogFields.java
 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/audit/AuditLogFields.java
index 98af46e30fd..bf167c743ce 100644
--- 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/audit/AuditLogFields.java
+++ 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/audit/AuditLogFields.java
@@ -79,6 +79,25 @@ public class AuditLogFields implements IAuditEntity {
         sqlString);
   }
 
+  public AuditLogFields(
+      long userId,
+      String username,
+      String cliHostname,
+      AuditEventType auditEventType,
+      AuditLogOperation operationType,
+      boolean result) {
+    this(
+        userId,
+        username,
+        cliHostname,
+        auditEventType,
+        operationType,
+        (List<PrivilegeType>) null,
+        result,
+        "",
+        "");
+  }
+
   public String getUsername() {
     return username;
   }
diff --git 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/auth/authorizer/BasicAuthorizer.java
 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/auth/authorizer/BasicAuthorizer.java
index ac86ae8d9fc..5d61b9e5e38 100644
--- 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/auth/authorizer/BasicAuthorizer.java
+++ 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/auth/authorizer/BasicAuthorizer.java
@@ -109,7 +109,8 @@ public abstract class BasicAuthorizer implements 
IAuthorizer, IService {
   public boolean login(String username, String password) throws AuthException {
     User user = userManager.getEntity(username);
     if (user == null || password == null) {
-      return false;
+      throw new AuthException(
+          TSStatusCode.USER_NOT_EXIST, String.format("The user %s does not 
exist.", username));
     }
     if (AuthUtils.validatePassword(
         password, user.getPassword(), 
AsymmetricEncrypt.DigestAlgorithm.SHA_256)) {
@@ -123,7 +124,7 @@ public abstract class BasicAuthorizer implements 
IAuthorizer, IService {
       }
       return true;
     }
-    return false;
+    throw new AuthException(TSStatusCode.WRONG_LOGIN_PASSWORD, "Incorrect 
password.");
   }
 
   @Override


Reply via email to