简体   繁体   English

Java JDBC-如何执行语句严格只读

[英]Java jdbc - how to execute a statement strictly read only

My server app uses prepared statements in almost all cases, to prevent sql injection. 我的服务器应用程序几乎在所有情况下都使用准备好的语句,以防止sql注入。 Nevertheless a possibility is needed providing special users executing raw SELECT queries. 但是,有可能需要提供特殊的用户来执行原始的SELECT查询。

How can I more or less securely make sure the query does not modify the database? 如何或多或少安全地确保查询不会修改数据库? Is it possible to execute a query read only, or is there any other 'secure' way making sure noone tries any sql injection? 是否可以执行只读查询,或者是否有其他“安全”方式来确保没有人尝试任何SQL注入? (Using sqlite3, so I cannot use any privileges) (使用sqlite3,所以我不能使用任何特权)

Thanks a lot! 非常感谢!

JDBC supports read-only connections by calling Connection.setReadOnly(true) . JDBC通过调用Connection.setReadOnly(true)支持只读连接。 However the javadoc says: 但是,javadoc说:

Puts this connection in read-only mode as a hint to the driver to enable database optimizations . 将此连接置于只读模式,以提示驱动程序启用数据库优化

Some JDBC drivers will enforce the read-only request, others will use it for optimizations only, or simply ignore it. 一些 JDBC驱动程序将强制执行只读请求,其他一些 JDBC驱动程序将仅将其用于优化或忽略它。 I don't know how sqlite3 implements it. 我不知道sqlite3如何实现它。 You'll have to test that. 您必须进行测试。

Otherwise, you could do a "simple" parse of the SQL statement, to ensure that it's a single valid SELECT statement. 否则,您可以对SQL语句进行“简单”解析,以确保它是单个有效的SELECT语句。

I'm not aware of a general JBDC configuration which specifies readonly. 我不知道指定只读的常规JBDC配置。 But Sqlite does have special database open modes and this can be leveraged in your connection to your sqlite database. 但是Sqlite确实具有特殊的数据库打开模式,可以在与sqlite数据库的连接中利用它。 Eg. 例如。

Properties config = new Properties();
config.setProperty("open_mode", "1");  //1 == readonly
Connection conn = DriverManager.getConnection("jdbc:sqlite:sample.db", config);

Credit: https://stackoverflow.com/a/18092761/62344 信用: https : //stackoverflow.com/a/18092761/62344

FWIW All supported open modes can be seen here . FWIW 在此处可以看到所有受支持的打开模式。

If you use some sort of factory class to create or return connections to the database, you can individually set connections to be read-only: 如果使用某种工厂类来创建或返回数据库连接,则可以将连接分别设置为只读:

public Connection getReadOnlyConnection() {
    // Alternatively this could come from a connection pool:
    final Connection conn = DriverManager.getConnection("jdbc:sqlite:sample.db");
    conn.setReadOnly(true);
    return conn;
}

If you're using a connection pool, then you may also want to provide a method for getting writeable connections too: 如果使用连接池,那么您可能还希望提供一种获取可写连接的方法:

public Connection getWriteableConnection() {
     final Connection conn = getPooledConnection(); // I'm assuming this method exists!
     conn.setReadOnly(false);
     return conn;
}

You could also provide just a single getConnection(boolean readOnly) method and simply pass the parameter through to the setReadOnly(boolean) call. 您也可以只提供一个getConnection(boolean readOnly)方法,只需将参数传递给setReadOnly(boolean)调用即可。 I prefer the separate methods personally, as it makes your intent much clearer. 我个人更喜欢使用单独的方法,因为这样可以使您的意图更加清晰。

Alternatively, some databases like Oracle provide a read only mode that can be enabled. 或者,某些数据库(例如Oracle)提供可以启用的只读模式。 SQLite doesn't provide one, but you can emulate it by simply setting the actual database files (including directories) to read only on the filesystem itself. SQLite不提供一个,但您可以通过简单地将实际数据库文件(包括目录)设置为仅在文件系统本身上读取来模拟它。

Another way of doing it is as follows (credit goes to deadlock for the below code ): 这样做的另一种方式如下( 对于以下代码,信用将变为死锁 ):

public Connection getReadOnlyConnection() {
    SQLiteConfig config = new SQLiteConfig();
    config.setReadOnly(true);
    Connection conn = DriverManager.getConnection("jdbc:sqlite:sample.db",
            config.toProperties());
 }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM