1 个不稳定版本
0.1.0 | 2023年2月14日 |
---|
#29 在 #postgre-sql
用于 concatsql
10KB
89 行
ConcatSQL
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