我的服务器应用程序几乎在所有情况下都使用预准备语句,以防止sql注入。然而,提供执行原始SELECT查询的特殊用户需要一种可能性。
我如何能够或多或少地安全地确保查询不会修改数据库?是否可以执行只读查询,还是有任何其他“安全”方式确保没有人尝试任何SQL注入? (使用sqlite3,所以我不能使用任何权限)
非常感谢!
答案 0 :(得分:4)
JDBC通过调用Connection.setReadOnly(true)
支持只读连接。然而,javadoc说:
将此连接置于只读模式,作为提示驱动程序启用数据库优化。
某些 JDBC驱动程序将强制执行只读请求,其他人将仅将其用于优化,或者只是忽略它。我不知道sqlite3
如何实现它。你必须测试它。
否则,你可以做一个简单的"解析SQL语句,以确保它是单个有效SELECT
语句。
答案 1 :(得分:2)
我不知道一般指定readonly的JBDC配置。但是Sqlite确实有特殊的数据库打开模式,这可以在你连接到sqlite数据库时使用。例如
Properties config = new Properties();
config.setProperty("open_mode", "1"); //1 == readonly
Connection conn = DriverManager.getConnection("jdbc:sqlite:sample.db", config);
信用:https://stackoverflow.com/a/18092761/62344
FWIW可以看到所有支持的开放模式here。
答案 2 :(得分:2)
如果使用某种工厂类来创建或返回与数据库的连接,则可以单独将连接设置为只读:
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;
}
如果您正在使用连接池,那么您可能还想提供一种获取可写连接的方法:
public Connection getWriteableConnection() {
final Connection conn = getPooledConnection(); // I'm assuming this method exists!
conn.setReadOnly(false);
return conn;
}
您还可以只提供一个getConnection(boolean readOnly)
方法,只需将参数传递给setReadOnly(boolean)
调用即可。我个人更喜欢单独的方法,因为它使你的意图更加清晰。
或者,像Oracle这样的某些数据库提供了可以启用的只读模式。 SQLite不提供一个,但您可以通过简单地将实际数据库文件(包括目录)设置为只读取文件系统本身来模拟它。
另一种方法如下(信用转到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());
}