首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用R中的RMariaDB和池清理发送到MariaDB的多个JSON字符串

使用R中的RMariaDB和池清理发送到MariaDB的多个JSON字符串
EN

Stack Overflow用户
提问于 2019-12-13 19:24:30
回答 1查看 159关注 0票数 1

我目前正在构建一个(大型)调查,需要将人们提供的答复发送到数据库。我已经使用poolRMariaDB包建立了我的数据库连接,并且我编写了以下函数来构造SQL查询并提交我的数据(数据使用SSL证书进行保护,所有这些信息都通过列表db_config传递)。

代码语言:javascript
复制
save_db <- function (db_pool, x, db_name, db_config, replace_val) {
  # Construct the DB query to be sent to the database
  if (!replace_val) {
    query <- sprintf(
      "INSERT INTO %s (%s) VALUES ('%s')",
      db_name,
      paste(names(x), collapse = ", "),
      paste(x, collapse = "', '")
    )
  } else {
    query <- sprintf(
      "UPDATE %s SET %s WHERE %s;",
      db_name,
      paste(paste0(names(x)[-1], " = \'", x[-1], "\'"), collapse = ", "),
      paste0(names(x)[1], " = \'", x[1], "\'")
    )
  }

  # Submit the insert query to the database via the opened connection
  RMariaDB::dbExecute(db_pool, query)
}

db_pool是处理数据库连接的池对象;x是包含我发送到数据库的数据的命名向量,其中的名称对应于我的MariaDB的列名,值存储为data blobs;db_name是我的数据库的名称;replace_val是布尔值。

数据斑点本质上是与调查不同的输出对象,例如响应的向量或矩阵,使用jsonlite包中的toJSON()转换为字符串。

到现在为止还好。我能够将数据发送到数据库,下载数据并使用fromJSON()命令重建响应。一切都很好。然而,我确实有一个安全问题。在我的调查中,我确实有一些开放式的问题,人们可以写他们想要的东西。虽然可能性不大,但我担心有人可能会使用SQL注入攻击。最坏的情况,我会丢失我所有的数据。

我从DBI包中知道了sqlInterpolate()函数。据我所知,该函数转义了任何引号,这意味着提交的任何值都将被转换为安全字符串。

我不能做的是修改我上面的函数来使用sqlInterpolate。在我的例子中,x是一个长度为7的命名向量,其中每个向量元素都是一个JSON字符串。实际上,我需要对每个JSON字符串使用sqlInterpolate()。我想知道是否有一种“简单”的方法来做这件事,或者我最好的做法是完全重写我的函数,向DB发送七个单独的存款,即每个向量元素一个。

一个相当简单的示例如下所示:

代码语言:javascript
复制
library(jsonlite)

# Create some data to test the string on
y <- 1:3
z <- matrix(runif(4), 2, 2)
q <- c("one", "don't")
x <- c(toJSON(y), toJSON(z), toJSON(q))
names(x) <- c("var_1", "var_2", "var_3")
db_name <- "my_db"

# Current sprintf() statement
sprintf(
  "INSERT INTO %s (%s) VALUES ('%s')",
  db_name,
  paste(names(x), collapse = ", "),
  paste(x, collapse = "', '")
)

我需要插入的是('%s')sprintf()语句中捕获的值(对于update查询也是如此)。因为我相当确定,只要将所有内容转换为JSON字符串,就可以净化我的DB输入?

任何帮助都将不胜感激。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-12-14 00:48:49

今天,我花了几个小时尝试这个问题,但失败了,我相信我设法找到了一个替代方案。我已经做了一些测试,它似乎正在工作。我正在张贴我自己的问题的答案,以防有人在不同的时间遇到类似的问题。

我更新的函数现在看起来像这样:

代码语言:javascript
复制
save_db <- function (db_pool, x, db_name, db_config, replace_val) {
  # Interpolate the elements of x
  x <- do.call(c, lapply(x, function(y) {
    sql <- "?value"
    sqlInterpolate(db_pool, sql, value = y)
  }))

  # Construct the DB query to be sent to the database
  if (!replace_val) {
    query <- sprintf(
      "INSERT INTO %s (%s) VALUES (%s)",
      db_name,
      paste(names(x), collapse = ", "),
      paste(x, collapse = ", ")
    )

  } else {
    query <- sprintf(
      "UPDATE %s SET %s WHERE %s;",
      db_name,
      paste(paste0(names(x)[-1], " = ", x[-1]), collapse = ", "),
      paste0(names(x)[1], " = ", x[1])
    )
  }

  # Submit the insert query to the database via the opened connection
  RMariaDB::dbExecute(db_pool, query)
}

关键似乎是只在实际的JSON字符串本身上使用插值,如下所示:

代码语言:javascript
复制
  x <- do.call(c, lapply(x, function(y) {
    sql <- "?value"
    sqlInterpolate(db_pool, sql, value = y)
  }))

函数的其余部分可以按原样使用。要了解这一点,让我们使用我在原始问题中提供的示例:

代码语言:javascript
复制
y <- 1:3
z <- matrix(runif(4), 2, 2)
q <- c("one", "don't")
x <- c(toJSON(y), toJSON(z), toJSON(q))
names(x) <- c("var_1", "var_2", "var_3")
db_name <- "my_db"

# Current sprintf() statement
sprintf(
  "INSERT INTO %s (%s) VALUES ('%s')",
  db_name,
  paste(names(x), collapse = ", "),
  paste(x, collapse = "', '")
)

这将产生输出:

代码语言:javascript
复制
"INSERT INTO my_db (var_1, var_2, var_3) VALUES ('[1,2,3]', '[[0.6573,0.1726],[0.3291,0.9903]]', '[\"one\",\"don't\"]')" 

如果我现在像上面那样转换x并使用更新的sprintf()调用(请注意,多余的单引号已被删除):

代码语言:javascript
复制
x <- do.call(c, lapply(x, function(y) {
  sql <- "?value"
  sqlInterpolate(ANSI(), sql, value = y)
}))

sprintf(
  "INSERT INTO %s (%s) VALUES (%s)",
  db_name,
  paste(names(x), collapse = ", "),
  paste(x, collapse = ", ")
)

我将得到:

代码语言:javascript
复制
"INSERT INTO my_db (var_1, var_2, var_3) VALUES ('[1,2,3]', '[[0.6573,0.1726],[0.3291,0.9903]]', '[\"one\",\"don''t\"]')"

我们可以看到,don't中的单引号被正确地引起来了。如果我在自己的解决方案中遗漏了一些重要的东西,请随时发表评论。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59321618

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档