【问题标题】:HSQLDB .script fileHSQLDB .script 文件
【发布时间】:2012-02-08 10:26:46
【问题描述】:

我以文件模式启动 HSQLDB。它运行得很好。当我的 Java 代码结束时,我通过发出 SHUTDOWN 优雅地关闭 HSQLDB。这将删除创建的临时文件,例如 .lck 和 .log 等。

但是,即使在 SHUTDOWN 之后,也始终存在两个文件 - .script 和 .properties。

如果我们想重新启动 HSQLDB 并连接到已经存在的数据库,我知道使用 .script。那挺好的。但是这个文件包含原始数据,因此可以很容易地修改。这可能是一个安全问题。

有人可以建议最好的可行方法来处理这个问题吗?我应该对 .script 文件进行编码吗?我仍然希望在稍后阶段连接到已经创建的数据库,因为这是我运行文件模式而不是内存模式的唯一原因。我不想使用服务器(内存中)模式。

我在 Windows7 上使用 JDK 1.7.0_02 和 HSQLDB 2.2.5。

谢谢。

【问题讨论】:

    标签: java hsqldb


    【解决方案1】:

    如果你害怕有人直接看到.script文件的内容你可以加密它:

    http://hsqldb.org/doc/2.0/guide/management-chapt.html#mtc_encrypted_database

    这将阻止用户查看文件中的真实数据。

    但这并不妨碍用户更改文件。如果用户对文件有物理访问权限,则无法阻止。

    【讨论】:

    • 感谢您的链接。这就是我一直在寻找的东西。但是, 1. 加密一般只有在有权访问加密密钥的用户是受信任的情况下才有效。这意味着必须向用户披露密钥。 2. 单个key不能用于多个数据库。是否有可能以某种方式在创建数据库时对其进行加密,并在稍后阶段访问它时自动解密(通过一些用户不知道的内部代码)。如果用户创建多个数据库,公开密钥仍然是一个令人头疼的问题。
    • 密钥可以隐藏在您的应用程序中,而不向用户公开。您可以为多个数据库使用相同的预生成密钥。
    【解决方案2】:

    在这里使用这个例子 -> http://www.hsqldb.org/doc/1.8/guide/apb.html

    我对代码做了一个微小的改动,它将使用 AES 密钥加密 *.script 文件。

    代码

    package com.gollahalli.main;
    
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.ResultSet;
    import java.sql.ResultSetMetaData;
    import java.sql.SQLException;
    import java.sql.Statement;
    import org.hsqldb.Server;
    
    public class Testdb {
    
        Connection conn;                                                //our connnection to the db - presist for life of program
    
        // we dont want this garbage collected until we are done
        public Testdb(String db_file_name_prefix) throws Exception {
    
            Class.forName("org.hsqldb.jdbcDriver");
    
            conn = DriverManager.getConnection("jdbc:hsqldb:"
                    + db_file_name_prefix, // filenames
                    "sa", // username
                    "");                      // password
        }
    
        public void shutdown() throws SQLException {
    
            Statement st = conn.createStatement();
    
            st.execute("SHUTDOWN");
            conn.close();    // if there are no other open connection
        }
    
    //use for SQL command SELECT
        public synchronized void query(String expression) throws SQLException {
    
            Statement st = null;
            ResultSet rs = null;
    
            st = conn.createStatement();         // statement objects can be reused with
    
            rs = st.executeQuery(expression);    // run the query
    
            dump(rs);
            st.close();    // NOTE!! if you close a statement the associated ResultSet is
    
        }
    
    //use for SQL commands CREATE, DROP, INSERT and UPDATE
        public synchronized void update(String expression) throws SQLException {
    
            Statement st = null;
    
            st = conn.createStatement();    // statements
    
            int i = st.executeUpdate(expression);    // run the query
    
            if (i == -1) {
                System.out.println("db error : " + expression);
            }
    
            st.close();
        }    // void update()
    
        public static void dump(ResultSet rs) throws SQLException {
    
            ResultSetMetaData meta = rs.getMetaData();
            int colmax = meta.getColumnCount();
            int i;
            Object o = null;
    
            for (; rs.next();) {
                for (i = 0; i < colmax; ++i) {
                    o = rs.getObject(i + 1);    // Is SQL the first column is indexed
    
                    // with 1 not 0
                    System.out.print(o.toString() + " ");
                }
    
                System.out.println(" ");
            }
        }                                       //void dump( ResultSet rs )
    
        public static void main(String[] args) {
    
            Server server = new Server();
            server.setDatabasePath(0, "file:./RemindMe;crypt_key=604a6105889da65326bf35790a923932;crypt_type=AES");
            server.setDatabaseName(0, "RemindMe");
            server.start();
    
            Testdb db = null;
    
            try {
                db = new Testdb("RemindMe");
            } catch (Exception ex1) {
    
                return;                   // bye bye
            }
    
            try {
    
                db.update(
                        "CREATE TABLE sample_table ( id INTEGER IDENTITY, str_col VARCHAR(256), num_col INTEGER)");
            } catch (SQLException ex2) {
    
            }
    
            try {
    
                db.update(
                        "INSERT INTO sample_table(str_col,num_col) VALUES('Ford', 100)");
                db.update(
                        "INSERT INTO sample_table(str_col,num_col) VALUES('Toyota', 200)");
                db.update(
                        "INSERT INTO sample_table(str_col,num_col) VALUES('Honda', 300)");
                db.update(
                        "INSERT INTO sample_table(str_col,num_col) VALUES('GM', 400)");
    
                // do a query
                db.query("SELECT * FROM sample_table WHERE num_col < 250");
    
                // at end of program
                db.shutdown();
            } catch (SQLException ex3) {
            }
    
            server.shutdown();
        }    // main()
    }    // class Testdb
    

    看看main 方法,它有这些行

    Server server = new Server();
    server.setDatabasePath(0, "file:./RemindMe;crypt_key=604a6105889da65326bf35790a923932;crypt_type=AES");
    server.setDatabaseName(0, "RemindMe");
    server.start();
    .....
    server.shutdown();
    

    当服务器运行时,HS​​QLDB 将创建一个扩展名为 .lck 的文件,该文件将一直存在,直到服务器关闭。

    要生成 AES 密钥,您可以使用 https://asecuritysite.com/encryption/keygen 或使用 CALL CRYPT_KEY('cypher_text', null);

    这应该可以解决问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-12-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-28
      • 1970-01-01
      相关资源
      最近更新 更多