#sql-database #postgresql #sqlite #mysql #sql

concatsql_macro

SQLite、MySQL 和 PostgreSQL 的安全库

1 个不稳定版本

0.1.0 2023年2月14日

#29#postgre-sql


用于 concatsql

MIT 许可证

10KB
89

ConcatSQL

Actions Status Crates.io Documentation License

ConcatSQL(concatsql) 是一个安全的 SQL 数据库库。
您可以使用字符串连接来防止 SQL 注入。

文档

支持的数据库

您可以在 Cargo.toml 中配置数据库后端

[dependencies]
concatsql = { version = "<version>", features = ["<postgres|mysql|sqlite>"] }

示例

正常值

let id     = String::from("42");    // User supplied input
let passwd = String::from("pass");  // User supplied input

let query = query!("SELECT name FROM users WHERE id={id} AND passwd={passwd}");
assert_eq!(query.simulate(), "SELECT name FROM users WHERE id='42' AND passwd='pass'");

for row in conn.rows(&query).unwrap() {
    assert_eq!(row.get(0).unwrap(),      "Alice");
    assert_eq!(row.get("name").unwrap(), "Alice");
}

危险值

let id     = String::from("42");             // User supplied input
let passwd = String::from("'' or 1=1; --");  // User supplied input

let query = query!("SELECT name FROM users WHERE id={id} AND passwd={passwd}");
assert_eq!(query.simulate(), "SELECT name FROM users WHERE id='42' AND passwd=''''' or 1=1; --'");

for row in conn.rows(&query).unwrap() {
    assert_eq!(row.get("name").unwrap(), "Alice");
}

如果您没有使用 query!

无法编译 ... 安全!

let id     = String::from("42");
let passwd = String::from("' or 1=1; --");
let query = format!("SELECT name FROM users WHERE id={id} AND passwd={passwd}");
conn.execute(&query).unwrap();  // error

当使用 query(<String>)

无法编译 ... 安全!

let age = String::from("50 or 1=1; --");
let query = query!("SELECT name FROM users WHERE age < ") + query!(age);  // error

为什么这个库可以防止 SQL 注入?

这是因为它是通过使用 运算符重载 而不是简单的字符串连接来实现的。
query! 宏返回库自己的类型(WrapString)。
例如,如果您将此 WrapString 类型与 String 类型组合,则转义的 String 类型将被组合,并返回一个新的 WrapString

struct WrapString<'a> {
    query:  Vec<Option<Cow<'a, str>>>,
    params: Vec<Value>,
}

let bar: String = String::from("bar");
let num: i32 = 42;
let foobar42: WrapString = query!("foo{bar}{num}");

foobar42 {
    query:  [Some("foo"), None, None],
    params: [Value::Text("bar"), Value::I32(42)],
}

ffi::sqlite3_prepare_v2(..., "foo??", ...);
ffi::sqlite3_bind_text(..., "bar", ...);
ffi::sqlite3_bind_int(..., 42);

许可证

MIT

依赖项

~2.5MB
~56K SLoC