HSQLDB .script 文件

Posted

技术标签:

【中文标题】HSQLDB .script 文件【英文标题】:HSQLDB .script file 【发布时间】: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。

谢谢。

【问题讨论】:

【参考方案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);

这应该可以解决问题。

【讨论】:

以上是关于HSQLDB .script 文件的主要内容,如果未能解决你的问题,请参考以下文章

hsqldb *.script.new 创建和删除

HSQLDB:.script 文件在多个项目执行[多线程环境]并行期间自动被删除?

如何让 HSQLDB 在从 .script 文件初始化数据源期间发出错误消息?

HSQLDB 在检查点期间在 db.script.new 文件上抛出 Asset failed 异常和文件 io 错误

JBOSS + HSQLDB 设置.script

从 HSQLDB 获取 ddl sql-script 的最简单方法是啥?