programing

RMariaDB 및 R의 풀을 사용하여 MariaDB로 전송된 여러 JSON 문자열 검사

skycolor 2023. 8. 30. 21:31
반응형

RMariaDB 및 R의 풀을 사용하여 MariaDB로 전송된 여러 JSON 문자열 검사

저는 현재 (대규모) 설문조사를 작성하고 있으며, 사람들이 제공하는 답변을 데이터베이스로 보내야 합니다.다음을 사용하여 데이터베이스 연결을 설정했습니다.pool그리고.RMariaDB패키지, 그리고 나는 SQL 쿼리를 구성하고 내 데이터를 제출하기 위해 다음 함수를 작성했습니다. (데이터는 SSL 인증서로 보호되며 이 모든 정보는 목록을 통해 전달됩니다.)db_config).

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의 열 이름에 해당하고 값은 데이터 블롭으로 저장됩니다.db_name내 데이터베이스의 이름입니다.replace_val부울음이 있는 사람

데이터 블롭은 조사와 본질적으로 다른 출력 객체입니다. 예를 들어, 벡터 또는 응답 행렬은 다음을 사용하여 문자열로 변환됩니다.toJSON()에서jsonlite꾸러미

지금까지, 좋아요.데이터베이스로 데이터를 전송하고 다운로드한 후 다음을 사용하여 응답을 재구성할 수 있습니다.fromJSON()지휘권모든 것이 좋습니다.하지만 한 가지 보안 문제가 있습니다.제 설문조사에서, 저는 사람들이 원하는 것을 쓸 수 있는 몇 가지 자유로운 질문이 있습니다.가능성은 낮지만, 누군가가 SQL 주입 공격을 사용하지 않을까 걱정됩니다.최악의 경우 데이터가 모두 손실됩니다.

나는 알고 있습니다.sqlInterpolate()의 기능DBI꾸러미제가 알기로는 함수는 따옴표를 제거합니다. 즉, 제출된 값은 안전한 문자열로 변환됩니다.

제가 할 수 없었던 것은 위의 기능을 작업하기 위해 수정하는 것입니다.sqlInterpolate내 경우에는x는 각 벡터 요소가 JSON 문자열인 길이 7의 명명된 벡터입니다.기본적으로 사용해야 합니다.sqlInterpolate()각 JSON 문자열에 있습니다.저는 이것을 "쉽게" 할 수 있는 방법이 있는지, 아니면 제가 할 수 있는 최선의 방법이 7개의 개별 예금을 DB로 보내는 기능을 완전히 다시 작성하는 것인지 궁금합니다. 즉, 각 벡터 요소에 대해 하나씩.

좀 더 단순화된 예는 다음과 같습니다.

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()문(업데이트 쿼리의 경우도 마찬가지입니다.모든 것을 JSON 문자열로 변환하는 것만으로도 DB 입력을 검사할 수 있다고 확신하기 때문에?

어떤 도움이라도 주시면 감사하겠습니다.

오늘 몇 시간 동안 이것을 시도했지만 실패했고, 저는 주변에서 일을 찾을 수 있었다고 생각합니다.제가 몇 가지 테스트를 해봤는데 효과가 있는 것 같습니다.혹시 다른 시간에 비슷한 문제가 있는 분이 계실까봐 제 질문에 대한 답변을 올립니다.

업데이트된 기능은 다음과 같습니다.

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 문자열 자체에 대한 보간만 사용하는 것으로 보입니다.

  x <- do.call(c, lapply(x, function(y) {
    sql <- "?value"
    sqlInterpolate(db_pool, sql, value = y)
  }))

그리고 나머지 기능은 그대로 사용할 수 있습니다.이를 확인하려면 원래 질문에서 제공한 예를 사용합니다.

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 = "', '")
)

그러면 출력이 생성됩니다.

"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()call("call"):

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 = ", ")
)

내가 받을 것:

"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의 단일 따옴표가 올바르게 따옴표로 표시되어 있습니다.만약 제가 해결책에서 중요한 것을 놓쳤다면, 그것에 대해 자유롭게 의견을 말해주세요.

언급URL : https://stackoverflow.com/questions/59321618/sanitizing-multiple-json-strings-sent-to-mariadb-using-rmariadb-and-pool-in-r

반응형